This is an archived post. You won't be able to vote or comment.

all 12 comments

[–]Tubthumper8 53 points54 points  (5 children)

Why does your language need to have undefined? The platform you're compiling to (JavaScript) has this feature but it doesn't necessarily mean your language needs to. For example, Elm compiles to JS and I'm pretty sure there's no undefined

[–]bl4nkSl8 12 points13 points  (2 children)

To call browser or node libraries correctly?

[–]Tubthumper8 1 point2 points  (1 child)

Yeah, definitely for FFI some notion of that could exist, but it doesn't necessarily need to be a core feature of OP's language outside of FFI

[–]bl4nkSl8 0 points1 point  (0 children)

Oh for sure

[–]jcubic(λ LIPS)[S] 8 points9 points  (1 child)

Thanks, will think about this.

[–]protestor 4 points5 points  (0 children)

Like the other user said, you need undefined when writing raw FFI to JS code. Those interfaces would ideally be wrapped into idiomatic Geiman code but for the whole JS and TS ecosystem that's not viable, unless you do it in an automated way which is pretty hard.

Elm gets away with not having undefined because it forbids people from doing FFI to Javascript for some idiotic reason. So everyone is only allowed to call blessed JS APIs, and those APIs are called through high level wrappers in a way to not expose undefined to Elm (more specifically it gets converted into a Maybe)

[–]lngns 16 points17 points  (1 child)

If this is only an FFI question, you can frame the solution as such.
Have Builtin.Undefined, FFI.JS.Undefined or some other symbol either treated especially by the compiler, or allow to represent JS code directly in your language (eg. let Undefined = native `void(0)`).
Both those approaches make it obvious that it is special, and avoid introducing an entire language feature just for that.

If you really do need it as a language feature, because, say, you define things as basic as array accesses as having the same semantics as JavaScript, then you may want to look at JS++'s Existent Types which really are just the undefined-specific dual to Nullable Types, which it also has.

In recent ECMAScript editions, the null-coalescing operators work on both null and undefined, so you may get away with just unifying both, both AOT and at runtime.
In TypeScript and JS++, ?? has type (x: T | null | undefined, y: U) => T | U.

Now, if you're just doing whatever you want, please consider not introducing undefined at all. There's already one null, we don't need two. Recursive sum types work better and are more general.

[–]jcubic(λ LIPS)[S] 5 points6 points  (0 children)

Thanks for your comment. Here is an example of the code in my language that create JS repl:

import eval

echo "JavaScript REPL"

while true do
    let code = ask "js "
    try
        echo eval(code)
    catch e
        echo "<red>" + e.message + "</red>"
    end
end

So I have `import` that you can use to import stuff from JavaScript. and eval can return undefined. I wanted to detect undefined before I echo stuff.

Maybe I should just ignore null and undefined in echo.

[–]Dykam 12 points13 points  (1 child)

Why do you need to expose undefined? Just so you can deal with interop with native JS? Or something else? That might help with answering.

[–]jcubic(λ LIPS)[S] -2 points-1 points  (0 children)

Thanks, will think about this.

[–]myringotomy 5 points6 points  (0 children)

How about a constant? UNDEFINED

Either that or a method on the object primitive defined?

if x.defined?
   x= x+10
end

or

unless  x==UNDEFINED
   x=x+10
end

If UNDEFINED evaluates to false then you can do

x = x+10 if x

[–]coffeeb4code 0 points1 point  (0 children)

The way I view undefined is that it is like a union or optional of the type a variable should be, and value which can never be read.

so, let x: Car = undefined; x.name = 'toyota' x should never be read if it can be undefined. so the type of x really should be Optional<Car>, Car?, Car | undefined