Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

This one is kind of interesting:

"Params: Function parameters must be named, but no need to repeat yourself, if the argument is named the same as the parameter (i.e. keyword arguments can be omitted). Inspired by JS object params, and Ruby."

I've grown fairly fond of JS implicitly named object parameters, and I always liked Smalltalk's named(-ish) parameters, and this seems like an interesting compromise. I'm not actually sure how Ruby works in this case? I thought its parameters were fairly normal. Are there other languages that do this?

But in the case of one-parameter functions this seems unnecessary, the function name often makes it clear exactly what the first parameter is. And if you are going to support Subject-Verb-Object phrasing (as suggested later) then the Subject is another implicit parameter that probably doesn't need naming.

Maybe another approach is that all functions take one unnamed argument, and there are structs with named members for any case when that single argument needs to contain more than one value. Which starts to feel like JS/TypeScript. The static typing to support this in TypeScript feels really complex to me (it's unclear if the language described uses static types).



OCaml gets all of this right already. Labels are optional (which is IMO better than the article suggestion). You can abbreviate to only the label if the parameter variable is the same as the label. You can omit the label for labelled parameters if you want, they just become unnamed positional parameters. And of course the main thing is type safety to help you get parameters right in many cases.

https://ocaml.org/manual/lablexamples.html https://dev.realworldocaml.org/variables-and-functions.html


The ability to treat named arguments as unnamed is not necessarily a feature - it's too easy for the caller to mistakenly pass the wrong thing without a label, and it also makes it that much harder for the API owner to version it in the future. Python adopted a special syntax for named-only arguments for these reasons.


(For others, labels are optional in three senses: not all parameters need to be labelled, the compiler can emit a warning if a label is omitted but you may want this to be an error instead, and there are optional labelled arguments which may be omitted entirely in some cases. Labels are not optional in that the type system is unwilling to convert between labelled/unlabelled or optional/omitted/required parameters and the compiler mostly won’t add hidden coercions between these types)

A common case where the trivial-value syntactic sugar fails looks like:

  foo ~some_descriptive_label:t.some_descriptive_label
  bar ~something:!something
Or

  baz ~the_option:config.the_option
(Why not just pass the config? Two reasons: it is nice to have the interface being explicit about what data is needed, and the function may come from a module that cannot depend on the definition of the config type.)


I'm surprisingly happy with IntelliJ / Java's behavior. Java is all positional parameters, but anytime the arguments aren't obvious, IntelliJ shows the parameter name with subtle syntax highlighting. It feels like the best of both worlds.

Completely random example, notice the 'limit':

https://monosnap.com/file/FU6QjZ6Y4b7CNmBBBZoUQlpO8YTXsR


It sound like java is not usable without the state-of-art IDE.


A ton of features on this list really require an IDE or rich program representation, or _something_ that's not just plain text. For instance using content hashes to refer to functions is only reasonable with IDE tooling support.


No, it means that tools can be made to improve the developer experience…


But programming language itself is a tool. And, you need one tool to improve the other, that imply your tool (programming language) is not good enough.

IMO, the only reason why java is still in use - superb IDE and tooling, that compensate terrible language design.


You've got it quite backwards. The superb IDE works synergistically with the language design to create an overall superior experience.

Poor language design (undecideable edge cases, dynamic and unpredictable meanings) makes it impossible to create a satisfying IDE experience.

If you're using vim or emacs to write code, you're wasting your employer's time. A good IDE makes you more productive.


I really dislike this feature, because it breaks cursor movement.


In what way?


(I'm a different person)

Vertical alignment. When you press the down arrow, you don't know what position your cursor will land on because it's not visually aligned with the character above. Kind of defeats the purpose of a monospace font (within that one line where it's applied).


> I've grown fairly fond of JS implicitly named object parameters, and I always liked Smalltalk's named(-ish) parameters, and this seems like an interesting compromise. I'm not actually sure how Ruby works in this case? I thought its parameters were fairly normal. Are there other languages that do this?

Ruby allows keyword arguments, which are very similar to object parameters in Javascript:

    # ruby
    def add(a, b, *args, x:, y:, **kwargs)
      puts a.to_s
      puts b.to_s
      puts args.to_s
      puts x.to_s
      puts y.to_s
      puts kwargs.to_s
    end

    add(1, 2, 3, 4, y: 'bar', x: 'foo', z: 'quux')
    # => 1
    # => 2
    # => [3, 4]
    # => foo
    # => bar
    # => {:z => 'quux'}
there are also 'splats', which are pretty much the same as array/object spreading in JS:

    # ruby
    positional_args = [1,2,3,4]
    keyword_args = { :x => 'foo', :y => 'bar', :z => 'quux' }
    add(*positional_args, **keyword_args)
    # => (same output as previous example)
One thing that's missing in Ruby (that I quite like in JS) is the ability to rename keyword arguments in the named parameter list, like:

    // javascript
    const example = ({ max: maxNum = 123 }) => {
      /* ... */
    };

    # ruby
    def example(max: 123)
      max_num = max # can't do this in the parameter list
      # ...
    end
Honestly, this limitation is just about the only thing I think is missing from Ruby's parameter-list syntax.

> But in the case of one-parameter functions this seems unnecessary, the function name often makes it clear exactly what the first parameter is. And if you are going to support Subject-Verb-Object phrasing (as suggested later) then the Subject is another implicit parameter that probably doesn't need naming.

Maybe there could be a special sigil for positional arguments? I like the idea of gently discouraging them, but still making them possible. Maybe something like

    // hypothetical language
    function singleArgFunction(@arg0: number) { /* ... */ }
    function mixedArgFunction(@arg0: number, foo: string, bar: string) { /* ... */ }
    function standardFunction(alfa: number, bravo: string) {/* ... */}

    singleArgFunction(0);
    mixedArgFunction(1, foo: 'hello', bar: 'world');
    standardFunction(alfa: 123, bravo: 'abc');


ruby 3.1 added the feature OP is quoting. If you have local variables x and y and the method definition

    def doit(:x, :y)
you can just call it with, IIRC:

    doit(x:, y:)
instead of

    doit(x: x, y: y)
as was needed before.


On your last point I’ve been toying with the idea of having even the function it self folded into that struct

the struct defines the unbound inputs ad well as mapping those to different named outputs

one interesting aspect to play around with is to then have commutative, and associative, application/evaluation operation where structs (or environments really) are merged and evaluated by binding what can be bound

say

(a,b:1+a)(b,a:1,c:a+b,d:2)

would evaluate to

(a:1,b:2,c:3,d:2)

not saying its a good idea - kind of falls down on scoping - bu could be an interesting toy.


This makes me think about some sort of exec-with-dynamic-scope approach to functions, like:

    func = {
        b = 1 + a
    }
    result = func {
        a = 1
        c = a + b
        d = 3
    }
Where func {...} (two adjacent blocks) is like a composition and merges the two blocks. "=" has the mathematical meaning, not assignment but a statement of equality. The parameters are just the free variables, e.g. func has a parameter of a. Are external routines or functions also parameters? I'm inclined to say yes, and that it's interesting to treat them as such.

This is all very Mathematica/Wolfram-like, with concrete expressions with undefined terms, different than functions that are executed.

The result has no real sense of order, and so it implicitly has to be purely functional. I can imagine using this to build things-that-execute, where this code doesn't execute but defines an execution (like tensorflow). Or there's some outside layer that creates streams of input, and the "execution" is how it responds to those streams. That outside layer is where all the system integration happens. It would work well with React-style unidirectional data flow. But I think for any practical program you'd have to live in both worlds.


I believe Ruby and OCaml have both anonymous positional arguments and keyword arguments with punning (i.e. `f ~arg` expands to `f ~arg:arg` in OCaml).


Good suggestions for improvement.

The latest Ruby version works as described in the «keyword arguments can be omitted» link.

The dream language is gradually static typed. Like TS, but the type system and inference would ideally be more like OCaml or ReScript. Hopefully avoiding some of the complexity of TS, and gaining more soundness.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: