Live data from Hacker News

Show HN: A small programming language where everything is pass-by-value

github.com

41–50 of 64 posts

Re: Show HN: A small programming language where everything is pass-by-value

#41

Curious if erlang/elixir isn’t the same sort of thing? Or am I misunderstanding the semantics of “pass by value”?

Your assumption is somewhat correct, for both Erlang and Elixir, however the phrase under discussion doesn’t mean the same thing for immutable languages. Both are ‘pass-by-value’ but that term is being overloaded in a particular way. As I said in another comment, ‘value’ in the language from TFA means any object that IS NOT a reference. The qualifier that every semantic object is a ‘value’ and that therefore, all arguments to a function call, threads spawn, etc are independent values which are (logically, at least) copied to new values that are then passed to the new context.

However, for Erlang and Elixir ‘pass-by-value’ is otherwise called ‘call-by-value’. In this case, it is a statement that arguments to functions are evaluated before they are passed into the function (often at the call site). This is in opposition to ‘call-by-name/need’ (yes, I know they aren’t the same) which is, for instance, how Haskell does it for sure, and I think Python is actually ‘by-name’ as well.

So, Herd’s usage here is a statement of semantic defaults (and the benefits/drawbacks that follow from those defaults) for arguments to functions, and Elixir’s usage is about the evaluation order of arguments to functions, they really aren’t talking about the same thing.

Interestingly, this is also a pair of separate things, which are both separate from what another commenter was pedantically pointing out elsewhere in the thread. Programming language discussion really does seem to have a mess of terminology to deal with.

Re: Show HN: A small programming language where everything is pass-by-value

#43

Earlier quoted context omitted.

cool project. can you take the address of a variable in some way? i.e. implement your own pointers if its really really needed?

> can you take the address of a variable in some way? I intentionally didn't add this, mostly because I wanted to explore how far you can get without it (and keep the language simple). Having a "real" pointer as a first class type wouldn't work though, since it would break a lot of the assumptions I use for optimizations. I did think about two different versions of this but didn't end up adding either: - Something li…

you're right, once indirection appears pandoras box opens up. keep it as pass by value only, it makes the language unique. although the desire for pointers will never go away, people have used them for so long now.

Re: Show HN: A small programming language where everything is pass-by-value

#44
post #27

the pipe-equal operator is pretty neat, don't think I've seen any other language do that.

I wrote the following and then realized maybe it is just a quirk of the example in the reader that the ‘set’/‘=‘ pair comes at the end of the chain. If so, it is just a unique syntax sugar for a function, I don’t think it is, so I’m leaving my comment as I wrote it letting this act as a caveat:

Although I don’t particularly like the ‘|’ to be used for chaining functions, I certainly know that it has been a long term syntax coming from Unix. My only issue with the ‘|=‘ is that it should be unnecessary. The only reason I can see that the special operator is required is that the ‘set’/‘=‘ syntax pair is a non-functional keyword ‘set’ with an (I think) overloaded keyword ‘=‘. If the equal sign was an ordinary function (i.e. a function that take a value, and an identifier, associates the value and the identifier, then returns the new value like the Lisps and derived lands) it could just be used arbitrarily in chains of functions.

Re: Show HN: A small programming language where everything is pass-by-value

#45

Earlier quoted context omitted.

> can you take the address of a variable in some way? I intentionally didn't add this, mostly because I wanted to explore how far you can get without it (and keep the language simple). Having a "real" pointer as a first class type wouldn't work though, since it would break a lot of the assumptions I use for optimizations. I did think about two different versions of this but didn't end up adding either: - Something li…

you're right, once indirection appears pandoras box opens up. keep it as pass by value only, it makes the language unique. although the desire for pointers will never go away, people have used them for so long now.

I think your statement about familiarity is spot on. One of the ‘promises’ of the early functional language efforts (late 70s through mid 90s) was that the invariants made it conceptually simple to have a magical, super compiler take the code and produce binary executables that would surpass imperative languages, due to the aforementioned Pandora’s box effect of the non-functional constructs. Universal value semantics are similar, especially without leaky abstractions allowing “please just let me crack the box, I’ll be good and won’t abuse the power”. Commitment to the invariants, in this case purely (logically, at least) value semantics across the entire language could produce executables that approach low-level, less restrictive code results with a much, much lower burden on the programmer.

Re: Show HN: A small programming language where everything is pass-by-value

#46
post #26

The threading story here is what grabbed my attention. Pass-by-value with copy-on-write means you get data-race immunity without any locks or channels. You just pass data to a thread and mutations stay local. That's a genuinely useful property. I've worked on systems where we spent more time reasoning about shared state than writing actual logic. The typical answer is "just make everything immutable" but then you los…

Why don’t we just do this by default for threading in most languages? It’s pretty rare for me to actually want to do memory sharing while threading (mostly because of the complexity)

Because it's super slow and shared memory is super fast. And people generally prefer fast code rather than safe code.

Re: Show HN: A small programming language where everything is pass-by-value

#47

At the risk of telling you what you already know and/or did not mean to say: not everything can be a value. If everything is a value then no computation (reduction) is possible. Why? Because computation stops at values. This is traditional programming language/lambda calculus nomenclature and dogma. See Plotkin's classic work on PCF (~ 1975) for instance; Winskel's semantics text (~ 1990) is more approachable. Things…

Excuse me if I didn't get it right, but as a practical example, I'd assume that I can rewrite every program into JavaScript using the usual control structures and, beyond that, nothing but string values (which are immutable). Simple arithmetic would already be kind of a chore but can be done. (Input and output already happens only via serialized values (cf also webworkers) so there's that; for convenience use TypedArrays wrapped in classes that shield you from immutability). It is not obvious to me where `a = '[1,2]'; a1 = JSON.stringify( JSON.parse( a ).push( 3 ) ) );` is fundamentally different from just pushing a value to a copy of `a`. Also, you could write `a1 = a.slice(0,-1) + '3]'` which only uses non-mutating stuff under the hood.

Re: Show HN: A small programming language where everything is pass-by-value

#48
This sounds quite similar to pure functional languages like Haskell, where a function call cannot have any side effect.

But those go further in that they don't even have any mutable data. Instead of

    var foo = { a: 1 };
    var bar = foo; // make a copy of foo
    set bar.a = 2; // modify bar (makes a copy)
Haskell has

    foo = Baz { a = 1 }
    bar = foo { a = 2 } // make a modified copy of foo

Re: Show HN: A small programming language where everything is pass-by-value

#49
post #48

This sounds quite similar to pure functional languages like Haskell, where a function call cannot have any side effect. But those go further in that they don't even have any mutable data. Instead of var foo = { a: 1 }; var bar = foo; // make a copy of foo set bar.a = 2; // modify bar (makes a copy) Haskell has foo = Baz { a = 1 } bar = foo { a = 2 } // make a modified copy of foo

Personally I think local mutability is quite a useful property, which was part of the inspiration for making this instead of just another pure functional language:

- All functions are still referentially transparent, which means we get all the local reasoning benefits of pure functions. - We can mutate local variables inside loops (instead of just shadowing bindings), which makes certain things a lot easier to write (especially for beginners). - Mutating nested fields is super easy: `set foo.bar[0].baz = 1;` (compare this to the equivalent Haskell).

Re: Show HN: A small programming language where everything is pass-by-value

#50
post #37

Earlier quoted context omitted.

Nope, it's value semantics (unlike Python), the references are just an internal optimization. Implicit copies happen when a list/dict with more than one reference is mutated.

> the references are just an internal optimization Optimization specifically for function calls, or... ? Because if you're doing all this copy-on-write anyway, the indirection seems to be a needless cost in other contexts.

This applies everywhere, and it fundamentally wouldn't be possible for just function calls.

> needless cost

Are you comparing to a language with mutable references or a our functional language? A language with mutable references will of course be faster, but this is more intended as an alternative to pure functional languages (since functions are referentially transparent).

In this case, the cost of the indirection is approximately zero (relative to the cost of just doing reference counting), since passing a reference just requires a bump to the refcount. And most of the time the refcount increments are skipped by "moving" instead of copying the reference.

Post reply on HN