Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon.

Pages: 1-4041-

Pure OO vs. Curried Syntax

Name: Anonymous 2010-08-07 23:18

So /prog/, I have looked around and I haven't been able to find any more-or-less pure OO languages with curried syntax. What gives?

It's not uncommon to see: object message message message

Where object message returns an object which accepts takes the next message, but what if the message is a method call that takes parameters? Instead of returning a curried object, you still get: object method(a,b) method(x,y), but never: object method a b method x y -- why is that?

Name: Anonymous 2010-08-08 0:46

It seems like it could only work if the parser knew that a and b are to be passed as arguments to method. In those cases, you couldn't have a nil argument (unless your parser could parse two whitespaces as a nil argument), but I don't see why it's not possible for non-nil arguments.

Name: Anonymous 2010-08-08 2:27

>>2
The parser? Even in an eval/apply scenario the parser is long gone by this point. 'method' might even be a run-time binding.

Name: Anonymous 2010-08-08 6:03

I don't think you understand the term 'currying'.

Name: Anonymous 2010-08-08 7:05

>>4
Curry my Butt.

Name: Anonymous 2010-08-08 12:55

With all the SICP lip service I thought /prog/ would at least have some interest/insight into PL theory. Maybe the weekend isn't such a great time.

Name: Anonymous 2010-08-08 13:19

>>6
Because the question is ridiculous
I have looked around and I haven't been able to find any more-or-less pure OO languages with curried syntax. What gives?
In the event that it actually doesn't exist, then maybe no-one actually wanted to implement one.  Simple as that.
As for the feasibility of such an idea, if you implemented "closure objects" a la SICP in a partial evaluating lisp then this would be the result.

Name: Anonymous 2010-08-08 16:04

Smalltalk cascades to the rescue
self hax: (self anus); age: 12; write: #ansiCCompiler

Name: Anonymous 2010-08-08 16:14

>>8
It's not quite what OP is wanting, and I can't say I find it easier to read than the usually foo.bar(baz).quux(xyzzy) notation.

Name: Anonymous 2010-08-08 18:23

>>9
What makes Object.method1(param1).method2(param2) so hard to read?  Even if you don't know exactly what it is doing, as long as you know how a single object uses a single method, you can easily imply that both methods act on the object in some order.
That's not necessarily a correct explanation but it is a logical conclusion.

Name: Anonymous 2010-08-08 18:30

>>10
You have misunderstood what I said. To reiterate
I can't say I find it easier to read than the usual foo.bar(baz).quux(xyzzy) notation.
In this sentence, ``it'' refers to >>8's example and I am saying that I do not find it easier to read than the ``usual'' notation. Or to put it another way foo.bar(baz).quux(xyzzy) > self hax: (self anus); age: 12; write: #ansiCCompiler

Name: Anonymous 2010-08-08 18:36

>>11
Sorry.  My mistake.

Name: Anonymous 2010-08-09 9:53

pure OO language
wat

Name: Anonymous 2010-08-09 10:38

>>13
I've heard two different meanings for that phrase. Either
a) everything is an object
or
b) objects are immutable (pure in functional sense)
I'd assume that OP is referring to (a), but I don't think it would have any bearing on his question anyway

Name: Anonymous 2010-08-09 14:40

Ioke is a huge ioke.

Name: Anonymous 2010-08-09 15:01

a) everything is an object
Makes sense.

b) objects are immutable
All objects?  That sounds like it would be inconvenient.

Name: Anonymous 2010-08-09 15:13

>>16
I would guess that it's up to the language designer

Name: Anonymous 2010-08-09 15:18

>>16
You've never used a language where everything is immutable.

Name: Anonymous 2010-08-09 15:25

>>18
No, I haven't.  Any suggestions?

Name: Anonymous 2010-08-09 15:26

This:

object message message message

is not the same as this:

object.func1(x).func2(y).func3(z)

because object.func1(x) doesn't necessarily return the same type as object.  You're calling func2(y) on something entirely different than object.

If you the same as object message message message in a language like C++, then you're going to have to force everything to derive from some base "object" class and you don't want that.

Name: Anonymous 2010-08-09 15:29

>>19
Pure Haskell.

Name: Anonymous 2010-08-09 15:36

everything is immutable.
That's only true for purely fictional languages.

Name: Anonymous 2010-08-09 16:44

I don't understand why someone would want a pure OO, assuming "pure" means "no side-effects." Just roll your own closures in some functional subset of a language.

Name: Anonymous 2010-08-09 16:44

>>20
1. No-one said it was the same thing
2. No-one said they wanted it to be the same object that received all those messages, of course, if you read OP's post you would know that
>>22
There is nothing that precludes an OO language being purely functional, or vice versa

Name: Anonymous 2010-08-09 17:54

>>19
a language where everything is immutable.
Assembly.  All you have are constants and methods that can modify some kind of foreign data that has no relevance to the actual language.

Name: Anonymous 2010-08-09 18:05

>>25
Terrible!

Name: 1 2010-08-09 18:38

>>13,14
I was referring to (a). It does affect things somewhat. If everything is an object, all objects, messages, functions/methods, return values will accept messages. If messages are being curried I think it muddies the waters a bit.

>>20
They're not the same, but with curried messages the second the becomes: object func1 x func2 y func3 z. The idea is that objects are returned just like you would normally do with closures, and they begin receiving messages. (Note: func1, 2, 3 could be bound functions or they could be messages by name or what-have-you, the end result is the same, the only thing that changes is how the receiver1 handles it (either by some internal method, or by creating a closure which applies the function to the next message.) This is what >>24 means by:
No-one said they wanted it to be the same object that received all those messages
In fact the objective is explicitly not to send those messages to the same object.

The objective is to do this automatically1, instead of having to build objects that do it so that you don't have to derive from a base object class. (Not that I don't mind doing that so much, assuming I can append to protos or whatever. I do believe C++ was sufficiently ruled out in the main post.)

1. Of course the receiver doesn't handle this in every instance of currying. Optimally, and especially with language support for it, it can be handled in the caller.

>>23
Aversion of side-effects is not what I had in mind by purity. "Everything is an object" is what I had in mind. I know purity is sometimes (often?) taken on its own to mean freedom from side effects, so I can see the confusion. I was referring to the purity of the concept.

I suspect that side effects can throw a wrench into things here too. On the other hand, forbidding them for the sake of argument also seems problematic to me.

Name: Anonymous 2010-08-09 18:41

Pure OO wins! flawless victory!

Name: Anonymous 2010-08-09 19:31

OP, have you looked at Ocaml? I don't know if it works for object methods, but IIRC, it does partial evaluation of normal functions.

Name: Anonymous 2010-08-09 21:57

INTANGIBLE, IMPRACTICAL ABSTRACT BULLSHITE.

Name: Anonymous 2010-08-09 22:10

Would you call a pure object oriented language a POOL or a POO language? Maybe I should make it a purely object oriented functional language, to be sure.

Name: Anonymous 2010-08-09 22:27

>>31
a POOF language?

Name: Anonymous 2010-08-09 23:25

>>31
Functional Object Oriented Language would probably get the message across just fine.

Name: Anonymous 2010-08-10 0:09

>>29
I have looked at it, but AFAIK OCaml doesn't provide a means to curry messages. Admittedly I haven't gotten too deep into it so I can't say with absolute certainty.

I have isolated a point of ambiguity that is possibly inescapable without adding syntax that causes the convenience benefits to evaporate; consider the following:

w x y

Suppose w is an object, according to the premise. x is a message, but is it the name of a method on w or is it a value to be supplied (where and how should it be evaluated?) Since all objects can be assumed to be happy to receive more messages, we can't simply consider whether w is a closure wanting more arguments since it's still an object and all objects appear the same in this regard (and arguments are being supplied as messages.)

Going along, suppose we decide we'll take whatever we can get. If x is a valid message (i.e. w contains a slot/property/member named 'x'), it will be treated as such. If not, it will be evaluated in the caller before being passed on. The problem of ambiguity arises when x qualifies as both. You can assign priority (probably to the caller), but you may want to use the alternative (eg. in the callee.) A simple '.' prefix might specify that x is intended as a message name: w .x y

Which is suspiciously similar to: w.x y

Which is precisely regular curried syntax with functions (in the event that w's x is a method accepting a single argument.)

As long as everything is an object I don't think there's a solution that ties everything up nicely. The surface landscape simply needs more variety. On the other hand, in the examples above it's likely that w .x y would be required only rarely and it might be usable if you don't mind seeing a sea of words without much (if any) punctuation of any kind.

Name: Anonymous 2010-08-10 7:52

>>34
but is it the name of a method on w or is it a value to be supplied (where and how should it be evaluated?
This is a failure to specify how you wanted messages to be represented. Since we had been talking about currying, I had assumed that a message was some first class value that was dispatched upon to return either another value and that in your examples 'message' could conceivably be any legal expression of the language that returned a message.

Since all objects can be assumed to be happy to receive more messages, we can't simply consider whether w is a closure wanting more arguments since it's still an object and all objects appear the same in this regard (and arguments are being supplied as messages.)
True, this was the decision you made when you decided to give message passing the same semantics as function application.

Going along, suppose we decide we'll take whatever we can get. If x is a valid message (i.e. w contains a slot/property/member named 'x'), it will be treated as such. If not, it will be evaluated in the caller before being passed on.
Yuck

The problem of ambiguity arises when x qualifies as both. You can assign priority (probably to the caller), but you may want to use the alternative (eg. in the callee.) A simple '.' prefix might specify that x is intended as a message name: w .x y
I see the problem, you wanted to treat a message as any other identifier. That was always going to bite you. Use anything else: a separate type, strings, numbers, lists, vectors, functions; just not identifiers, since you'll get fucked over by your scoping rules.

Which is precisely regular curried syntax with functions
Which is what you wanted, right?

--  Example
(define (make-object x y)
  (letrec ((foo x)
       (bar y)
       (dispatch
        (lambda (disp)
          (case disp
        ;; assuming symbols are messages, they are treated normally
        ((foo) foo) ;field accessors
        ((bar) bar)
        ((set-bar!) (lambda (val)
                  (set! bar val)))
        (else ; if the "message" has a different type
         (cond ((string? disp) ; a string can be a message too
            (dispatch (string->symbol disp)))
               ((list? disp) ; if a message is a list, dispatch on each
            (map dispatch disp))
               ((vector? disp) ; ditto for vectors
             (vector-map dispatch disp))
               (else ; or whatever
            (error "Can't dispatch on message" disp))))))))
    dispatch))
;Value: make-object

(define o (make-object 2 3))
;Value: o

(o 'foo)
;Value: 2

(o 'bar)
;Value: 3

(o 'set-bar!)
;Value 19: #[compound-procedure 19]

((o 'set-bar!) 89)
;Value: 3

(o 'bar)
;Value: 89

(o '(foo bar))
;Value 20: (2 89)

(let ((v (o '#(bar set-bar!))))
  ((vector-ref v 1) 80)
  `(before ,(vector-ref v 0) after ,(o 'bar)))
;Value 21: (before 89 after 80)

(o 'bar)
;Value: 80

((o 'set-bar!) 89)
;Value: 80

Name: 35 2010-08-10 8:02

>>34
You need to explicitly curry, but this is a transcript from my repl that I think shows what you want
        Objective Caml version 3.11.2

# class foo =
object (self)
  val mutable bar = 9
  method get = bar
  method set x =
    bar <- x;
    bar
end;;
              class foo :
  object val mutable bar : int method get : int method set : int -> int end
# let quux = new foo;;
val quux : foo = <obj>
# quux#get;;
- : int = 9
# quux#set 3;;
- : int = 3
# quux#get;;
- : int = 3
# (quux#set);;
- : int -> int = <fun>
# (quux#set) 10;;
- : int = 10
# quux#get;;
- : int = 10
# class bar =
object (self)
  val mutable baz = new foo
  method get = baz
  method set x =
    baz <- x;
    baz
end;;
              class bar :
  object val mutable baz : foo method get : foo method set : foo -> foo end
# let xyzzy = new bar;;
val xyzzy : bar = <obj>
# (xyzzy#get);;
- : foo = <obj>
# (xyzzy#get)#get;;
- : int = 9
# (xyzzy#get)#set;;
- : int -> int = <fun>
# ((xyzzy#get)#set) 88;;
- : int = 88
# ((xyzzy#get)#get);;
- : int = 88
#

Name: Anonymous 2010-08-10 8:11

I forgot to show "object message arg message" behaviour
        Objective Caml version 3.11.2

class foo x =
object (self)
  val bar = x;
  method get = bar
  method make_added x y =
    new foo (x + y)
end;;
#             class foo :
  int ->
  object
    val bar : int
    method get : int
    method make_added : int -> int -> foo
  end
# let bar = new foo 9;;
val bar : foo = <obj>
# bar#get;;
- : int = 9
# bar#make_added;;
- : int -> int -> foo = <fun>
# (bar#make_added) 4;;
- : int -> foo = <fun>
# ((bar#make_added) 4) 3;;
- : foo = <obj>
# (((bar#make_added) 4) 3)#get;;
- : int = 7
#

Name: Anonymous 2010-08-10 10:36

HAX MY SYNTAX

Name: Anonymous 2010-08-10 14:11

>>35
I had assumed that a message was some first class value that was dispatched upon to return either another value and that in your examples 'message' could conceivably be any legal expression of the language that returned a message.
I did mention (I think) that messages were to be objects. I don't think using an expression in place of 'message' changes anything, although you would have to signify evaluation.

Yuck
Of course. It's just an example. It's also common in my experience, with the happy coincidence that the problem with it almost never arises. (This is why I started with this example, then reversed it by the end of the paragraph. If there is a conflict it is easier on the programmer if the caller has the preferred ground.)

I see the problem, you wanted to treat a message as any other identifier.
It's a good way of putting it. I fully admit to introducing a confusion. It took me a little longer than it should have to realize that without extra syntax or extreme measures of some kind, there is no way back to stable ground when the language permits that kind of conflict.

Speaking of extreme measures, I had considered message objects with special (i.e. semantically relevant) properties. Unbound identifiers could easily be considered message constructors. It's an organic version of the 'preferred caller' solution.

Which is precisely regular curried syntax with functions
Which is what you wanted, right?
Well, not quite. Function currying is common. It's when messages are thrown in to the currying process that I am interested in. I do have that with some caveats and I would be satisfied with w .x y, except that much of the goal is to eliminate method call syntax. On the other hand, that form is only really needed in certain cases (eg. when the caller is subject to change, though this might fall under "maintainability" too) and it does seem like it helps even if it's not everything that was desired.

The OCaml examples don't immediately help because it should all be implicit. I didn't really make this clear, and I guess I should have. On the other hand: (bar#make_added 4 3)#get;; is not bad, but too bad about the parens. In a serious language this is probably the better way to do it anyway, and you wouldn't catch me complaining about having to use this.

Name: Anonymous 2010-08-10 14:36

>>39
The OCaml examples don't immediately help because it should all be implicit. I didn't really make this clear, and I guess I should have.
No, you did, but it was the closest analogue I could find.

On the other hand: (bar#make_added 4 3)#get;; is not bad, but too bad about the parens.
The other parens are unnecessary in Ocaml, but it was put there to get the *exact* same behaviour as if they were curried, in normal code you would do (bar #make_added 4 3) #get ;;. Maybe you could convince the Ocaml guys to give a "currying mode"? I notice that the other functional + oo languages like F# and Scala don't provide the behaviour you want either.

Name: Anonymous 2010-08-10 16:01

>>40
Ah, I think I was a bit unclear after all:

The other parens are unnecessary in Ocaml, but it was put there to get the *exact* same behaviour as if they were curried
Assuming the result is functionally equivalent, that's enough. It's syntax currying that has my interest, without being concerned so much with whether it is actually being curried mechanically. It's advantageous to optimize the process away, though not required. I would still require a partial application to yield a closure of course.

Maybe you could convince the Ocaml guys to give a "currying mode"?
I'm not sure it would be worth it. I posted this thread hoping it would be more interesting than the average fare here lately, although I am personally interested in the exploration of the idea. I think there are a lot of rough edges that should be explored before adopting a syntax like this. (I'll admit I'm half considering doing an esolang based on the idea. It's not quite as crazy as, say, Dieter: http://catseye.tc/projects/dieter/doc/website_dieter.html)

Name: Anonymous 2010-08-11 3:59

bump

Name: Anonymous 2010-08-11 4:06

66SHUT THE FUCK UP99
-Expert LUA programmer.

Name: Anonymous 2010-08-11 8:01

Syntactic pseudo-“programming” thread.

Don't change these.
Name: Email:
Entire Thread Thread List