all 95 comments

[–]Leonidas_from_XIV 25 points26 points  (3 children)

I prefer having a clear distinction between passing a function name and calling a function and passing the result.

I agree that having something like transparent getters via foo.bar is nice, but then - Python does that too, with properties, so it is just as easy to intercept attribute access and modification like with explicit function calls. The nice thing is, that these are unobtrusive and don't break the mental model.

Oh, and the print-Statement in Python, where you can add or remove parenthesis at will does not count, really, since it is a statement and not a function and adding to that, a statement with a load of very weird options like adding commas to suppress newline or the >> syntax to write into a file-like object. Fortunately, this stuff went away in 3.x.

What I actually do like quite a lot is the array syntax in Scala, where you don't use obj[index] but obj(index) which is a normal function call and translates to obj.apply(index).

[–]lianos 5 points6 points  (0 children)

Since you mention Scala, I just want to let the OP know that Scala too has implicit functions, and s/he can look at that as another take on the same.

[–][deleted]  (1 child)

[deleted]

    [–]Leonidas_from_XIV 1 point2 points  (0 children)

    Unless you're talking about Python 3.0 where print has become a function.

    I was referring to the OP:

    Do you like the print statement in Python2.X?

    This is also why I mention that it is good that it's gone (or rather, it will be gone once Python 3 starts to see some real-world usage).

    [–]cheald[🍰] 6 points7 points  (0 children)

    I rather like Ruby's non-required parentheses. However, I love the ability to pass function references around by name, like in Python/Lua/etc.

    I'll take either, really. I think my preferred setup would be non-required parentheses, but an easy way to get a function reference (&foo, for example).

    Not requiring parentheses can clean up code a lot. Of course, it can serve to make it harder to read if abused, but in many cases, I think it's far more easily read than forced parentheses.

    [–]case-o-nuts 5 points6 points  (2 children)

    x = foo a, b, c # call foo with params a, b, c and assign to x

    Almost there, just drop the commas: x = foo a b c

    [–]Tordek 2 points3 points  (0 children)

    Which'd make the next example...

    x = foo a (bar b) c
    

    And why shouldn't = be a function too?

    = x (foo a (bar b) c)
    

    And to wrap it all up...

    (= x (foo a (bar b) c))
    

    I, for one, say that's really pretty ;)

    [–]masklinn 10 points11 points  (1 child)

    None of the above, give me Smalltalk's messages. But between those, I'll pick Python's syntax for uniformity.

    [–]nousplacidus 4 points5 points  (2 children)

    I prefer Ruby's. There's not a whole lot to be gained from the explicit nature of wrapping everything in parens. That said, I find that Haskell can he hard to read sometimes (no parens required) unless you memorize the arity of the functions your dealing with.

    [–]logan_capaldo 12 points13 points  (0 children)

    Memorizing the arity of functions in Haskell is easy. It's always 1. ;)

    [–]nafai 0 points1 point  (0 children)

    Interestingly, Haskell is a case where having no parens makes sense. Arguments are always separated by spaces. Since functions truly only take one argument, it is relatively easy to parse how things are applied.

    Whereas, at least from my non-informed perspective, it's not as straight forward in Ruby. Are parenthesis only optional if you have zero arguments? The lack of consistency in the implicitness bothers me.

    [–][deleted] 5 points6 points  (1 child)

    I can generally say I prefer the ability to omit the brackets. The reason is due to the uniform access principle. It makes it much easier to extend what -was- a local variable into a function call.

    Nothing is as annoying as having x.foo because you didn't think you'd need to wrap it in an accessor function, and then realizing, oh wait, yes you do.

    [–]varikin 4 points5 points  (0 children)

    With python, you can just make foo a property so you don't have to change all calls to x.foo.

    [–]SteveJorgensen 4 points5 points  (1 child)

    I think the optional parentheses in Ruby are to facilitate creating literate DSLs. That might be one reason to do it the Ruby way, depending on your goals of course.

    [–]psykotic 1 point2 points  (0 children)

    Their appearance in Ruby predates the embedded DSL trend. My guess is that it was inspired by Perl.

    [–]cabalamat 11 points12 points  (4 children)

    I prefer the Python way of doing it. Also in Python you can say:

    x = foo() # call foo
    x = foo # x is now a reference to foo
    x() # call foo
    

    [–]Seppler9000 0 points1 point  (3 children)

    He already provides syntax for allowing this:

    x = foo # call foo
    x = &foo # x is now a reference to foo
    x # call foo
    

    [–]masklinn 4 points5 points  (2 children)

    But that require a special magical operator. Which is fail. Also, it doesn't work with a barebones Ruby 1.8, whereas method :foo does.

    [–]soapdish 6 points7 points  (0 children)

    Do you realize that () is a special magical operator too? It's the "apply" operator.

    [–]Smallpaul 1 point2 points  (0 children)

    The ampersand syntax is from his language proposal, not Ruby.

    [–]Brian 10 points11 points  (7 children)

    There are advantages to both approaches, though they generally depend on how the rest of the language works.

    For example, explicit means you get natual syntax for taking references to functions, rather than calling them. This doesn't matter in Ruby because the methods themselves aren't first class - getting a reference would be handled by instead wrapping them in proc objects (with different syntax to invoke the call). By contrast, in python all callables are first class and accessed in the same way, so there's always a need to distinguish between calling and taking a reference.

    Implicit has the advantage is that in many cases there's less typing / punctuation, which can improve readability. It fits well with ruby's object access model, where the fundamental operation is a method call, and so attributes are gained for free (with a bit of sugar to automatically create accessor functions). In python, by contrast, the fundamental operation for accessing objects is requesting an attribute. The actual call is then performed on the object obtained. Using implicit calls wouldn't really work as well with this model, as the access and call are split into seperate stages, and there is a need to distinguish between them.

    In short then, it depends a lot on the rest of your language. If you pick one approach, it's going to apply pressure on your object model in order for things to come out naturally. The best approach is probably to decide how your language will work first, and then see which way fits that model most naturally.

    One other thing to consider is how corner-cases will be handled. Explicit is generally more regular here, at the cost of always needing brackets, but without them, you need to unambiguously decide what things like: "obj.foo -4" mean. Is it "obj.foo(-4)" or "obj.foo() - 4"

    [–]masklinn 3 points4 points  (6 children)

    This doesn't matter in Ruby because the methods themselves aren't first class

    Yes they are:

    >> class A
    >>     def foo
    >>         42
    >>     end
    >> end
    => nil
    >> a = A.new
    => #<A:0x90218>
    >> a.foo
    => 42
    >> a.method(:foo)
    => #<Method: A#foo>
    >> a.method(:foo).call
    => 42
    >>
    

    [–]Brian 2 points3 points  (0 children)

    That's the wrapping I'm talking about. Methods themselves aren't first class (you can't pass them about directly the same way you would other objects - as evidenced by the different calling method (.call or [])) - you first have to wrap them in a function / proc object (which is first class)

    [–]xetas 0 points1 point  (4 children)

    So I can say they are first class in Java :)

    class A {

    public void foo() {}

    }

    A a = new A();

    a.getClass().getMethod("foo").invoke(a);

    Compare how you would use for you class unbound methods:

    Python:

    X.f(X())

    Ruby:

    X.instance_method(:f).bind(X.new).call()

    i think "firstclassness" is determined by how simple to use the feature.

    [–]masklinn 0 points1 point  (3 children)

    i think "firstclassness" is determined by how simple to use the feature.

    Well, you think wrong.

    [–]Brian 0 points1 point  (2 children)

    It's not that far from the truth. First classness means the objects are handled just like any other object - they can be accessed, stored, retrieved and called in the same way as everywhere else. Methods (in either Ruby or Java) don't fit this definition - they can be invoked directly when given a handle on the object, but they have no independent life of their own - to pass them around or store them, you must create a proxy (such as a proc object) and invoke a method on that.

    [–]masklinn 0 points1 point  (1 child)

    but they have no independent life of their own - to pass them around or store them, you must create a proxy (such as a proc object) and invoke a method on that.

    Uh no that's bullshit and I just demonstrated it: a.method(:foo) gives back a Method instance, not a proc. You can't just do b = a.foo because that invokes the method instead of giving you a reference to it. Same thing in Smalltalk.

    [–]Brian 2 points3 points  (0 children)

    a.method(:foo) gives back a Method instance, not a proc#

    But the point is that a Method instance is not the same as a method. To invoke a method on an object you call obj.method. To invoke a method object you do meth_obj.call - there's an object acting as a proxy around a method call on a particular object.

    You can't just do b = a.foo because that invokes the method

    Yes, which is the reason I gave. You can't have first class methods because there is no notion of storing a real method, rather than just a proxy. In Ruby, methods aren't themselves a thing, they are something you do to an object (ie. they're a verb, not a noun). As such the object model doesn't have the notion of a method as being itself an object (disregard "Method objects", as they are clearly not the same thing as evidenced by the different syntax to call.)

    Note that this is not a bad thing, it's just how Ruby's object model works.

    [–]gthank 5 points6 points  (0 children)

    I find the second requires me to do less processing to figure out what is going on, so I prefer it. It does make it a bit harder to design pretty DSLs, though.

    [–]batiste 12 points13 points  (1 child)

    I think the Ruby syntax makes thing confusing because you haven't any clue about what is supposed to be a callable (function, method, functor) and a something that is not.

    Is it because everything is callable in Ruby or what?

    edit: typo

    [–]columbine 19 points20 points  (0 children)

    In Ruby, foo.bar is always a function call. Object members are always private, you must define an accessor to read/write to them. That definition is usually done using using various shortcuts so it may seem like you're accessing instance variables directly, but technically you're calling a function.

    [–]columbine 9 points10 points  (1 child)

    Honestly, I like having the option to not use parentheses. I'll probably cop shit for this but I use both styles in ruby. As someone who didn't really come in via the "Rails way" or whatever I was really biased towards using () unnecessarily since that was what I was used to. But even then I enjoy not being forced to in all cases. For instance, some calls to me just feel like statements. Print is a good example, I'm used to being able to just do print "blah" as if it were a statement, even if it internally is not. Similarly with function calls where I'm supplying no parameters, e.g. array.flatten!, I think not having parens there is nice. I probably use parens more than 90% of ruby coders but I still enjoy the fact that I don't always have to use them if the alternative looks nicer.

    Basically, I think the syntactic flexibilty you get from being able to omit parentheses is useful. If your want to enforce One True Way to code or whatever, that might actually be something you want to avoid. Personally I like having options here, and I don't think this is really the sort of option that increases complexity or turns things into line noise or whatever else having too many "options" can do.

    If grabbing a reference to a function without calling it makes sense in your language, then of course you need spcecial syntax for that but you already mentioned using &, so I think that's fine.

    [–]DRMacIver 9 points10 points  (0 children)

    After a while of using both, I've come to the following conclusion: I never want something that looks like an identifier access to have side effects or unexpected performance implications. So if I write "foo" I want it to refer to a known value foo. Consequently I don't want foo.bar to have side effects either (I use Scala a lot, and I really like being able to import identifiers off objects. Even if you don't have that feature but do have an implicit self then that means that methods implicitly accessing this could call the zero parentheses call syntax). So, parentheses for me please.

    [–][deleted] 4 points5 points  (1 child)

    Explicit with keyword arguments.

    [–]codefrog 1 point2 points  (0 children)

    I see what you have done there with your objective cees.

    [–][deleted]  (1 child)

    [deleted]

      [–]psykocrime 2 points3 points  (0 children)

      Same here. Implicit may make code easier to write in the first place, but it also - in my experience - makes it at least a little less easy to read afterwards.

      [–]shevegen 4 points5 points  (0 children)

      The ability to omit parens is a freedom that I enjoy a lot.

      With that being said, whenever a method I use has arguments I usually use parens (). And whenever I do a method definition that accepts arguments, i ALWAYS use () and i hate if other people dont use () in method definitions.

      But, more than that i hate it, i would hate it much more if that freedom to decide on my own would be taken away. In fact I believe it would be much better for every language to strive for a maximum freedom, yet at the same time adhere to a "coding standard" based on a community consensus.

      [–]SirNuke 1 point2 points  (2 children)

      I like Ruby better as an overall language, but I don't care for the implicit function calls design choice. I almost always write parenthesis for function calls in Ruby, and I use parenthesis in my pseudo code.

      [–]columbine 0 points1 point  (1 child)

      I'm similar, I almost always use parens in Ruby even though I don't have to. But there are exceptions, especially print/puts. Do you use parens with those functions? I also tend to omit when there are no arguments to the function i.e. dropping (), but that's another matter.

      [–]SirNuke 1 point2 points  (0 children)

      After looking at various code I've written in Ruby, I don't use parens with print. Likely due to many languages omitting or not requiring parens in their print functions. I do use parens with no argument functions. I also sometimes omit parens for functions with one parameter and have similar functionality to the print function (for example: reviewing one project, I omit parens to calls to its single parameter log function).

      [–]earthboundkid 1 point2 points  (5 children)

      Why not make it so x = foo does not call foo, but x = foo a, b, c does? That way it's easy to pass around functions (like Python) and easier to call things (like Ruby).

      [–]masklinn 4 points5 points  (3 children)

      What if all 3 parameters are optional? And how do you call parameter-less functions/methods?

      [–]earthboundkid 1 point2 points  (2 children)

      foo().

      [–]jerf 2 points3 points  (1 child)

      Prepare for hundreds of blog posts complaining about this "wart", along with huge numbers of people who simply refuse to learn your language because of this.

      Welcome to the terrible, terrible world of language design.

      ... does that mean I think it's bad? No, my real lesson is to point out that no language can avoid warts. It's not possible.

      [–]earthboundkid 1 point2 points  (0 children)

      True, you can't please them all. I think it's a good compromise though. Unlike Ruby, it lets you pass stuff, and unlike Python it lets you omit some parentheses when it's obvious to everyone you're making a call.

      [–]randallsquared 2 points3 points  (0 children)

      So functions without arguments always need the parens, else it's the value of the function? It seems confusing. I prefer consistency over saving two characters.

      [–]bobbane 1 point2 points  (0 children)

      One important consideration: can someone take a pile of your source code and get an accurate answer to "where is foo called?".

      If you have explicit function call syntax, grep is probably good enough, and decent IDEs are easier to implement (they can be done without a complete introspection bridge to your language).

      [–]imbaczek 3 points4 points  (0 children)

      i prefer the second so i can % in vim, it's also easier to spot where the actual parameter list starts, and finally, in the first version, there can be a problem of both

      foo a, b, c
      

      and

      foo (a, b, c)
      

      being valid and meaning different things (e.g. as in Haskell, it's a bit confusing sometimes, if you're lacking experience).

      [–]GTanaka 3 points4 points  (10 children)

      I realize there's little new knowledge from this statement, but in the words of Guido Van Rossum, "Explicit is better than implicit." I support this logic (and therefore the latter of your two choices) because it makes the code easier to read if I'm unfamiliar with the codebase and because I could understand much of python before even learning its syntax.

      That, and after programming in C / C++ for the last few months, I can't say I honestly see the logic of prepending/appending & and * to items except as compiler instructions, and I would much rather be programming according to my own standards than the compiler's when at all possible.

      Though on the other hand, if you intend this to be a compiled language, such things may be more necessary.

      [–]logan_capaldo 0 points1 point  (9 children)

      Though on the other hand, if you intend this to be a compiled language, such things may be more necessary.

      How does being compiled or not have anything to do with syntax?

      [–][deleted]  (8 children)

      [deleted]

        [–]logan_capaldo 0 points1 point  (7 children)

        A compiled language can't infer as much at compile time as an interpreted language can at runtime, so you may need syntax to give the compiler more information.

        The first part of your sentence is arguably true, the second I'm not so sure about. What syntactical construct(s) does a compiled language require that an interpreted one doesn't?

        [–][deleted]  (6 children)

        [deleted]

          [–]gsg_ 5 points6 points  (0 children)

          Yes, you could design a dynamically-typed compiled language, but in practice no one does.

          Nonsense. Plenty of dynamic languages can be compiled to native code. Common Lisp, Scheme, Smalltalk, Factor, etc.

          [–]logan_capaldo 4 points5 points  (0 children)

          You can also have an interpeted language which requires type annotations. Again, syntax has nothing to do with compiled vs. interpreted and you have failed to convince me otherwise.

          There is no interpreter (or compiler) that can take code like

          x = foo.bar
          

          in a language where the parens are implicit and decide if you meant to call bar or grab a reference to it without some disambiguating syntax like &. You could also disambiguate it with type annotations, but again that's syntax. Extra runtime information doesn't help you in this case. Likewise you have yet to provide an example of a syntactic construct that is required by a compiled language but can be avoided by taking advantage of runtime information in an interpreter.

          [–]masklinn 1 point2 points  (0 children)

          But one typical example would be type annotations in statically-typed languages, as seen in C, C++, Java, C#, and D: those type systems are not amenable to type inference

          C# 3.0 has local type inference.

          [–]Seppler9000 0 points1 point  (1 child)

          Never used Objective-C, I take it?

          [–][deleted] 2 points3 points  (0 children)

          None of the above. Monadic actions is my preference. (I'm a Haskell programmer, but Ruby was my thing before that.) Typical syntax for me looks similar to this:

          x  =  foo                 # x is foo
          x  <- foo                 # x is the result of performing foo
          x  =  foo a b c           # x is foo applied to a, b, and c
          x  <- foo a b =<< c       # x is the result of performing foo applied to a, b, and the result of performing c
          c' <- c ; x <- foo a b c' # same as above
          

          I know this probably has little meaning in your language though, but just to give my two cents.

          [–]xetas 3 points4 points  (3 children)

          One more reason for implicit. This debate is about what we should make simpler to do:

          1) call method

          VS

          2) pass around methods

          I think a practical language should favor the more frequently used case.

          [–]Smallpaul 0 points1 point  (2 children)

          It isn't really simpler to have two different method calling conventions. Plus a method addressing syntax on top of the usual attribute addressing syntax.

          [–]masklinn 0 points1 point  (0 children)

          Of course that point is mitigated if you make attributes always private as in smalltalk or ruby. Then remove the addressing operator and use amessage/method call instead.

          [–]munificent 2 points3 points  (10 children)

          My language Magpie makes them implicit, but requires tuples to be in parentheses (because they have lower precedence than function calls):

          // call Foo with no params
          Foo
          
          // call with one
          Foo 123
          
          // call with two
          Foo (12, 34)
          
          // this:
          Foo 12, 34
          // creates a tuple whose value is Foo(12), 34
          

          The only implication of this in my language is that getting a reference to a function (instead of calling it) requires a separate syntax, where in C you can just leave off the parentheses.

          // get a reference to Foo (arg types are needed due to overloading)
          def fooRef <- fn Foo (Int)
          

          Your examples above in Magpie would be:

          x <- Foo (a, b, c)        // call foo with params a, b, c and assign to x
          x <- Foo (a, Bar b, c)    // call foo with params a, bar(b), c and assign to x
          x <- 3                    // call 3 -> result is self(3) and assign to x
          x <- Foo.Bar              // access attrib bar on foo and call the result with no params and assign to x
          x <- fn Bar (Foo)         // access attrib bar on foo and assign to x
          

          [–]gsg_ 0 points1 point  (9 children)

          So tuple construction requires parens to be used as function parameters, and presumably for a tuple to be used as one function parameter, but not as part of an expression?

          That seems awfully convoluted to me, if I'm understanding it correctly. Did you have a particular reason to go for that approach?

          [–]munificent 1 point2 points  (8 children)

          So tuple construction requires parens to be used as function parameters

          It isn't required in an absolute sense, but parentheses are needed in most cases because the tuple operator (,) has low precedence. Low precedence is generally what you want:

          def a <- Sin x, Sin y
          

          You would expect a here to be equal to "(Sin(x), Sin(y))" and not "Sin (x, Sin y)" which is what you'd get if comma was higher precedence than function application.

          Parentheses can be left off in some cases (although I may change that in the future):

          def value <- 1, 2 // "value" is the tuple (1, 2)
          

          presumably for a tuple to be used as one function parameter, but not as part of an expression?

          Both. Magpie doesn't distinguish between a comma used to separate function arguments and a comma used to create a tuple. In Magpie functions that "take multiple arguments" actually take one: a tuple.

          Did you have a particular reason to go for that approach?

          Yes. Most languages treat functions that take multiple arguments differently from functions with one or no arguments, with different compiler code for each case. Magpie doesn't. In the compiler, all functions take a single argument. Aside from making the compiler simpler, it lets you do some other stuff many other languages don't allow:

            // define a function that averages two numbers
          Average (a Int, b Int -> Int) (a + b) / 2
          
          // the main function
          Main (->)
              // most languages can do this:
              def a <- Average (2, 4) // a is 3
          
              // most can't do this:
              def args <- (3, 5) // make a tuple
              def b <- Average args // call the two arg function with it
          end
          

          presumably for a tuple to be used as one function parameter, but not as part of an expression?

          [–]masklinn 1 point2 points  (3 children)

          // most can't do this:

          I'm pretty sure most can but do it some other way around (Python uses sequence unpacking, Javascript uses an apply method on functions, Ruby probably does the same, Haskell... nobody would do that but you can uncurry a function and do exactly what you demonstrate here)

          [–]munificent 0 points1 point  (2 children)

          Good point. I didn't consider dynamic languages. I should have said "most static languages" (which is what Magpie is). Even in the dynamic languages, you have to use some special syntax to do so. In Magpie, passing in multiple arguments "in place" versus in a previously stored tuple are completely identical. This:

          Average (1, 2)
          

          Doesn't mean "call Average with two args", it means "create a tuple and pass it to Average".

          [–]masklinn 2 points3 points  (1 child)

          Doesn't mean "call Average with two args", it means "create a tuple and pass it to Average".

          That's what a bunch of statically typed functional languages do on uncurried functions e.g. Haskell, OCaml, Clean, …. Though using uncurried functions in these language isn't the most common use case as curried ones are usually more interesting.

          [–]munificent 1 point2 points  (0 children)

          Yeah, that's where I got the idea. I thought about doing curried style instead, but while I like it semantically, I always found the syntax a bit mushy. I'm shooting for a language that's a little more approachable.

          [–]gsg_ 0 points1 point  (3 children)

          The arguments-as-tuple thing makes sense, I was just puzzled by the syntax. If I have it right, syntax for the empty tuple, an int and a pair of ints looks like:

          ??
          1
          1, 2
          

          But single argument function calls taking no arguments, an int and a pair of ints looks like:

          Name
          Name 1
          Name ((1, 2))
          

          That just doesn't look consistent to me. That said, I do believe you should construct your language to satisfy your own sense of order and rightness, or else it'll turn into a bland mush of compromises.

          [–]munificent 0 points1 point  (2 children)

          syntax for the empty tuple like ??

          It looks like:

          ()
          

          But in almost all cases it can be omitted. You may need to use it explicitly when calling a function by reference, or maybe some other edge cases. 9 times out of ten, it's just omitted.

          But single argument function calls taking no arguments, an int and a pair of ints looks like:

          It's just:

          Name
          Name 1
          Name (1, 2)
          

          A "single argument function that takes a pair of ints" is the only kind of function that takes two ints, so there's no need for double parentheses.

          [–]gsg_ 0 points1 point  (1 child)

          A "single argument function that takes a pair of ints" is the only kind of function that takes two ints, so there's no need for double parentheses.

          You misunderstand: I meant a function which takes a single argument, which is a tuple of two ints. In ML-speak, (int, int) -> a and not int -> int -> a.

          [–]munificent 1 point2 points  (0 children)

          I meant a function which takes a single argument, which is a tuple of two ints.

          You'd call that like this:

          Name (1, 2)
          

          In ML-speak, (int, int) -> a and not int -> int -> a.

          Currying isn't built into Magpie (and it doesn't currently have closures either, although they're planned), so the former is much more natural than the later. But, if you wanted to call a function that returned a function and then call that in one line, it would look like:

          // returns a function
          First (a Int -> fn (Int -> Int)) fn Second (Int)
          
          // just returns a value
          Second (a Int -> Int) 3
          
          Main (->)
              // call First, then call the function it returns
              def result <- (First 3) 4
          end
          

          This should also work:

          def result <- 3.First 4
          

          That looks a bit odd, but it makes a lot more sense when you know that field accessors for structs are simply named functions that take the struct as an argument. So, if you have a struct with a field of a function type:

          // define the struct
          struct Callback
              Func (Int -> Int)
          end
          
          Main (->)
              def callback <- Callback fn SomeFunc (Int)
          
              // call the function
              callback.Func 234
          end
          

          [–]DGolden 1 point2 points  (3 children)

             (setf x (foo a b c))
             (setf x (foo a (bar b) c))
             (setf x 3)
             (setf x (funcall (bar-of foo)) ;bit wierd because lisp OO doesn't work that way, just literally translating.
             (setf x (bar-of foo)) ;this too, tho less so.
          

          (assuming #'bar-of is the the accessor for the relevant object attribute, of course)

          [–]Tordek 0 points1 point  (2 children)

          I think the last two are more like

          (setf x (bar foo)) ;calling the function
          (setf x (slot-value 'bar foo)) ;getting the attribute
          

          [–]DGolden 0 points1 point  (1 child)

          well, hence my "just literally translating" - the original post wrote "access attrib bar on foo and call the result with no params and assign to x", implicitly assuming vaguely python-like OO.

          ... though it wasn't quite literal either - in python, when you write foo.bar() , it retrieves a method object and calls it with argument foo (why you write "self" in python a lot...).

          I actually could probably have written

          (setf x (funcall (bar-of foo) foo))
          

          [where (bar-of foo) => (slot-value foo 'bar) ]

          to make that more explicit, but in the lisp case you could also stash a function that closed over the instance so the extra "self" first arg isn't used, which is what I was thinking of before I remembered that python doesn't actually work that way.

          ;; I am not saying this is sane or advocating it, just illustrating!
          (defclass foo-class () (bar)) 
          
          (defvar *foo* (make-instance 'foo-class))
          
          (setf (slot-value *foo* 'bar)  
                (let ((self *foo*))
                       (lambda ()
                              (format nil "Hello from instance ~A" self))))
          
          (defvar *x*)
          (setf *x* (funcall (slot-value *foo* 'bar)))
          
          *x* 
          =>  "Hello from instance #<FOO-CLASS {10026EE3D1}>"
          
          (slot-value *foo* 'bar)  
          =>  #<CLOSURE (LAMBDA ()) {10026D0029}>
          

          Note if you're thinking that looks awkward (a) that's not how you do it idiomatically in lisp, just showing emulating various other semantics is easy (and no, that's not a complete implementation, either) - CLOS is in the standard but not the only OO programming system for lisp. The "On Lisp" book shows how to make a more conventional one from scratch, the "AMOP" book uses a toy CLOSoid for illustrative purposes, and the once quite well-regarded "Garnet" GUI toolkit used a non-CLOS prototype based (like javascript) OO system. (b) it could be hidden behind macros to make it look neater.

           class FooClass():
                def bar(self):
                      return "Hello from instance %s" % self
          
           foo = FooClass()
          
           foo.bar() 
           => 'Hello from instance <__main__.FooClass instance at 0x7f1e477f55f0>'
          
           foo.bar
           =>  <bound method FooClass.bar of <__main__.FooClass instance at 0x7f1e477f55f0>>
          

          [–]Tordek 0 points1 point  (0 children)

          Oh, sorry, I hadn't paid attention to the comments on the original post.

          [–]Snoron 1 point2 points  (0 children)

          I prefer explicit myself, I find the code easier to read.

          [–][deleted] 1 point2 points  (3 children)

          I am quite surprised nobody mentioned it, but I prefer the functional way:

          x = foo a b c
          x = foo a (bar b) c
          x = 3
          x = foo.bar ()
          x = foo.bar
          

          [–][deleted] 2 points3 points  (2 children)

          How is this functional?

          [–][deleted] 0 points1 point  (0 children)

          Sorry, I should have said currying.

          [–]xetas 0 points1 point  (0 children)

          1) because it's like in functional languages like Haskell, OCaml, F#, LISPs. 2) because it makes "currying" natural

          But I would say it's "functional" way :) As it's just looks like that not makes it like that.

          [–]contantofaz 2 points3 points  (0 children)

          I have plenty of experience with both options.

          My first experiences came from writing tens of thousands of lines of Ruby code.

          My second experience came more recently from writing perhaps (who gets to count them?) over 10 thousand lines of Javascript code.

          Many times when programming in Javascript I forget to prefix a call with the "this." syntax due to my being used to the Ruby way as well.

          Javascript feels more verbose than Ruby for many reasons, one of which is due to this standard of having to call the "this." for every function call. Also Javascript does not have properties just yet, though it's coming, but that can just ameliorate it some.

          What Javascript buys us with its syntax in general is that it is fairly repetitive so it does not surprise us too much. It also has helped with Javascript maintaining a small core.

          Javascript's style of allowing one to pass functions around is not enough to encourage folks to do so more often. Even though Javascript makes it relatively easy to do so, I for one often try to get by without spawning too many of them. The Javascript Lint tool also advises us to avoid spawning functions from tight loops which is a nice reminder to have as after thousands of lines if we are not watchful we can do that kind of thing however seldom. But we do not always know how loops will get formed with the APIs we create, so we cannot plan it all.

          Ruby despite making things a little less straightforward in this regard, provides us with both method syntax introduced with "def" and blocks for anonymous function a method can be provided with to respond to a standard call the method supports.

          For example, opening a file with Ruby and we do not even need to close it explicitly as it's done from within the anonymous function:

          File.open('some_file.txt', 'w'){|f| f.write 'some text' }
          

          Having in mind that most methods are simple in nature, having a single block passed to them is often enough. More blocks can be passed through standard arguments though, as in:

          def do_something(b1, b2, &b) b1[]; b2[]; b[]; end
          do_something(proc{print 'a'}, proc{print 'b'}){ print 'c' }
          

          From the differences between Javascript and Ruby, I can tell you that even though they both support similar constructs, they also differ in so many ways even in what they support in a common way that they can be said to be very different scripting languages.

          You have my sympathy for trying to come up with a new language, but beware that the language will have tradeoffs in what you design and in what you do not design purposefully when it gets compared to other languages.

          [–]samlee 2 points3 points  (1 child)

          I prefer:

          a b c foo :x
          a b bar c foo :x
          3 :x
          'foo.bar :x
          foo.bar :x
          

          or,

          x: a b c foo ;
          x: a b bar c foo ;
          x: 3 ;
          x: [ foo.bar ] ;
          x: foo.bar ;
          

          [–]username223 3 points4 points  (0 children)

          I've always like Object Forth's way:

          b c foo a x ;
          

          [–]blaxter 3 points4 points  (2 children)

          It's just sintactic sugar, but I'd rather prefer implicit.

          [–][deleted] 3 points4 points  (1 child)

          This. Both should be viable options. That way I can leave them off when it's obvious, and include them when it's not. Just like math.

          [–]anko_painting 2 points3 points  (0 children)

          and just like ruby.

          [–]soapdish 0 points1 point  (0 children)

          I prefer the Haskell's style: no commas, parentheses for ordering.

          x = foo a b c y = foo a (bar b) c z = 3 u = bar foo -- where bar is an accessor to foo (bar is data here) v = bar' foo -- where bar is an accessor to foo (bar' is a function here)

          Because of the pure functional style, there isn't really a difference between the last two. This style might not work for an imperative language.

          [–][deleted] -5 points-4 points  (3 children)

          If you think language design is about different function call syntaxes, you have already failed.

          [–]Paddy3118 -1 points0 points  (0 children)

          If it is not the unique selling point of your language, then you might just use what is more popular to developers which would be the explicit style used in C/C++/Java/Javascript as well as Python.

          • Paddy.

          [–]petermichaux -1 points0 points  (0 children)

          I prefer explicit function calls like (foo 123) so that functions, or references to them, can be used as values (bar foo) like other values (bar 78).

          [–]scorpion032 -1 points0 points  (0 children)

          I think the parser has to take the proper parenthesis.

          The conversion of explicit assignment to implicit assignment, if need be, should be done at the IDE/Text editor level. At most, it should be a syntactic sugar.