Conversation

eli, vampire kitsune

i think the idea of a wrapper class should have more first class support in languages

inheritance: hey, i-

no

1
1
4

@rowan will try me best in my WIP language neofox_floof_happy kind of like Value Classes in Kotlin, would you say? https://kotlinlang.org/docs/inline-classes.html

1
0
1

@vivi i haven’t read all of this documentation yet (and i’m also not super familiar with kotlin) but this actually seems perfect! the idea of a lightweight wrapper class to provide domain specific context / methods / computed values (and maybe even share the same identity as the inner value, or be easily coercible) is ideal

1
0
0

eli, vampire kitsune

Edited 7 months ago

@vivi i find myself wanting to reach for classes in Javascript as thin wrappers, but it’s really hard to unwrap them. valueOf() works implicitly when doing an operation with another primitive, but that’s often not enough. rust can kinda do this with stuff like the newtype pattern with impl AsRef and From/Into. that generally does what i want

as a specific use case that i have right now, i’d love to wrap WebGL/WebGPU stuff in helper classes for myself and be able to pass them around as if they were their inner values, but also give myself a way to deal with them in fewer than 716 calls to do a single useful thing

2
0
1

@vivi i could do this with proxies in javascript but in my specific example they’ll be used in the hot path (renderer system) so the performance implications make them unusable

0
0
0

@rowan yeah this is kinda what Kotlin value classes do. for instance like the example in the documentation i linked, you can create a wrapper value class Password(val backing: String) which wraps over a String, and you can define functions as members of the Password class like fun printObscured(withChar: Char = '•') = times(backing.length) { print(withChar) }.. in compiled code, except for cases where the value class is required dynamically (like in in-position of a function i.e. fun foo(takes: Password), Password does not technically exist at all and that printObscured function actually ends up just being compiled down to something like (non-member function) fun printObscured(string: String, withChar: Char = '•') = times(string.length) { print(withChar) } by the compiler, and calls to it (nor general constructor calls like val myPassword: Password = Password("password1234") do not literally create an instance of the Password class when instantiated, just the backing instance i.e. val myPassword: String = "password1234". "boxing" and "unboxing" so to speak, happen opaquely and without additional verbose burden on the programmer,,
Anyways it's really cool sorry for kotlin infodumping neofox_floof_happy

1
1
1

eli, vampire kitsune

Edited 7 months ago

@vivi aaa this seems perfect neofox_melt_sob_heart i’m not sure if you’re familiar much at all with C#, but it gives me the impression that methods are implemented kinda analogously to C#’s extension methods? where they’re actually static methods which are implicitly given the target object as the first parameter when called with dot notation? (the target is identified by the this Moss self part in my example below)

public static bool IsMoss(this Moss self) {
  return true;
}

var vivi = new Moss();
if (vivi.isMoss()) {
  vivi.hold(duration = PositiveInfinity);
}
1
0
1

@rowan yessss neofox_floof_happy Kotlin has extensions functions as well, but value classes just kinda take it a step further and are more like, extension classes neofox_up_paws a little more structured (like the printObscured here cannot apply to a regular String in source code, only a Password, even though when compiled it treats it as if it were a String anyways

also neofox_hug_heart neofox_hug_heart neofox_hug_heart neofox_hug_heart neofox_snuggle i don't think that duration is long enough vivi_heart

0
0
0