Arc Forumnew | comments | leaders | submitlogin
1 point by Pauan 4771 days ago | link | parent

Yes, except rocketnia doesn't like coerce either. I do like coerce, and I think it's a good idea for `each` to coerce to 'cons (or a similar iterable thing). I think coerce + extend + message passing would make for fantastically short and extensible code.

---

"Nobody here is scared of anything, least of all 'OOP words'. You may find it more helpful to phrase us as 'unconvinced that methods are needed in a lisp'."

I have already produced plenty of evidence that extend is over twice as verbose as message passing, more difficult to use, and doesn't play well with modules. When it comes to describing data types, I have not seen a single advantage that extend has over message passing. What more do you want? Should message passing do tap dancing too?

  (def tap-dancer ()
    (annotate 'dancer
      (fn (m)
        (case m
          'tap-dance (prn "tap dancing now")
                     (err:string "did not understand the message " m)))))

  (= dancer (tap-dancer))
  (dancer 'tap-dance)   -> "tap dancing now"
  (dancer 'break-dance) -> error: did not understand the message break-dance


2 points by rocketnia 4771 days ago | link

"Yes, except rocketnia doesn't like coerce either."

For the record, that's true, but I do follow a coercion pattern sometimes. See the end of http://arclanguage.org/item?id=14220: "To digress a bit, coercion is a positively useful design pattern when...."

As it happens, 'each is one of those times I'd use a coercion pattern. I'd probably define these utilities, with these dependencies:

  each  -->  some  -->  seqify  -->  entries  -->  keys  -->  unwrap-my-table
To introduce the type 'my-table and give it support for 'each, I only need to extend 'keys so that it tries 'unwrap-my-table.[1] If I do that, 'seqify will already be able to coerce my type to a lazy list.

[1] If the system doesn't support failcall, I may also have to extend 'supports-keys so that it tries 'isa-my-table. The diagram would be about twice as big if I included these predicates.

-----

1 point by akkartik 4771 days ago | link

I am not convinced your tiny example proves anything. We aren't playing code golf here to make things shorter by any means. Expressive constructs make for shorter programs, and I still believe methods are no more expressive than anything else. I think you're moving parens around.

One way to add evidence is to actually have an implementation of an arc-like language with methods (like I have done with wart). And I don't mean half-baked pseudocode that I have to spend time massaging. (http://arclanguage.org/item?id=14288) Who knows if I would massage it like you would have? You're leaving too much unspecified to persuade me.

"What more do you want? Should message passing do tap dancing too?"

I'm not going to respond if you talk like that.

Keep running with your ideas instead of waiting for us to catch up. If they're good you'll eventually bring us around. Expecting validation from others before moving onward is a recipe for misery. So we're fools. Ignore us.

-----

1 point by Pauan 4771 days ago | link

...what? "moving parens around"?

http://arclanguage.org/item?id=14261

Look at the first example there. That is a perfectly reasonable and trivial thing to do (creating a table that can inherit from another table). Message passing is less than half the size of wart... And that was without implementing iso and fill-table, which would make wart even more verbose...

That is not "moving parens around". This is a clear example where message passing is less than half as verbose as extend. Message passing should always be at least as good as extend, and in some situations will be significantly better. If you would rather use extend and write programs that are over twice as long, then go ahead... but I thought one of the main points of Arc was brevity.

---

"I'm not going to respond if you talk like that."

It was a joke.

---

"One way to add evidence is to actually have an implementation of an arc-like language with methods (like I have done with wart)."

As said, I plan to implement this in py-arc.

---

"Keep running with your ideas instead of waiting for us to catch up. If they're good you'll eventually bring us around. Expecting validation from others before moving onward is a recipe for misery. So we're fools. Ignore us."

Yes, you're right. I simply don't understand why, when I present clear evidence that extend is either equal to, or worse than message passing in every way pertaining to data types... it isn't accepted. What is it that is preventing acception? Is the evidence not clear? Are my words confusing?

-----

1 point by akkartik 4771 days ago | link

...what? "moving parens around"?

If you would rather use extend and write programs that are over twice as long, then go ahead

How would your approach clone from strings rather than from tables? Those are the sorts of questions I am talking about. Are methods useful if they can only clone tables?

The main point of arc is brevity across a range of programs.

"As said, I plan to implement this in py-arc."

I enjoy our discussions, but I don't understand how I am expected to be persuaded in the absence of running code. I'm happy to agree to disagree until you have something I can take the trouble to install, run, and make your complaints in http://arclanguage.org/item?id=14313 about :)

-----

1 point by Pauan 4771 days ago | link

Strings are annotated conses, so you can use message passing for them too. Message passing works for all data types, even int and num. What does "cloning a string" even mean, by the way?

Let me look at an example that is a bit more string-oriented: we want to make a string that can do substring searches with function notation. In other words, we want this to work:

  (= my-string (pos-string "foobar"))
  (my-string "foo") -> 0
  (my-string "bar") -> 3
  (my-string 0)     -> #\f
  (my-string 3)     -> #\b
Here's how to do that with message passing:

  (def pos-string (x)
    (annotate 'string
      (fn (m k . rest)
        (case m
          'get (case (type 'k)
                 'string (posmatch k x)
                         (apply x m k rest))
               (apply attr x m k rest)))))
How would you do this with extend? Can it be done without extending every single built-in that uses strings?

-----

1 point by rocketnia 4771 days ago | link

Here's a hopefully clearer and less buggy version of your example:

  (def pos-string (orig-string)
    (annotate 'string
      (fn (message key . rest)
        (if (and (is message 'get) (isa key 'string))
          
          ; This message represents a function call with a string as the
          ; first argument. Let's use 'posmatch for that.
          (posmatch key orig-string)
          
          ; We don't handle this message. Let's use 'attr to propagate
          ; raw message to the original.
          (apply attr orig-string message key rest)))))
---

"Can it be done without extending every single built-in that uses strings?"

There aren't that many axiomatic things strings do in Arc. In my mind, a custom string type would only have to support two operations: being called as a function; and being coerced to a lazy list, sent through a function, and coerced back. If a string-like thing supports those two behaviors, the core utilities should be able to handle it.

Arc's strings also support 'sref, but I pretend they don't. :-p

The "being coerced to a lazy list, sent through a function, and coerced back" utility may seem overcomplicated. It's the solution I prefer to enable this behavior:

  arc> (map inc "abcde")
  "bcdef"
This is implemented in pg-Arc using a 'coerce back to the input type, but if a pos-string has a type of 'string, then coercing the output to its original type will probably just make a core string, rather than a pos-string.

-----

1 point by Pauan 4771 days ago | link

"less buggy"? You're using k when it should be key. :P It is shorter, though, so thanks for that.

---

"There aren't that many axiomatic things strings do in Arc"

Yeah, I know. Tables seem to be the big pain point. Possibly conses too, if somebody wanted to extend those... tables seem like they'd be the most common thing to extend, though, and also the trickiest.

---

"[...] being coerced to a lazy list, sent through a function, and coerced back [...]"

Oh! Oh! I know! Let's use message passing! :P We can give strings an 'iter message! Just like Python! Whooo! I'm reminded of the Jamie Zawinski quote, "Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems."

Actually, I think it'd just be easier to define a `coerce` rule for 'iter, no need for message passing in that situation. Now, as for the actual creation of iterators, that could be done with message passing. :P

Then again... you're right that if pos-string uses the same type 'string as built-in strings, then `coerce` won't be able to know that it should use pos-string... unless you added in a message to the iterator, of course. But then that won't play as well with coerce...

I guess that is one example where the current way of coerce + extend + new-type-every-time is actually better.

-----

1 point by rocketnia 4771 days ago | link

"You're using k when it should be key. :P"

Fixed! Now it oughta be less buggy. ^^

---

"Tables seem to be the big pain point. Possibly conses too[...]"

I could be wrong, but I think it's enough for a table to extend 'keys, function call behavior, and 'sref. <Insert usual disclaimer that there'd need to be predicates like 'supports-keys in the absence of failcall.>

For Penknife's purposes, the only reason I care about cons cells is that they're eager implementations of nonempty lazy lists. They should support function call behavior, 'sref, and the one and only lazy list operation:

  (iffirst first rest seq
    <...thing to do with first and rest if the seq isn't empty...>
    <...thing to do if the seq is empty...>)
If cons cells are mutable and allowed to be improper, then they need 'scdr too, and it might be more elegant to add 'scar, 'car, and 'cdr.

-----

1 point by Pauan 4770 days ago | link

"I could be wrong, but I think it's enough for a table to extend 'keys, function call behavior, and 'sref."

And the built-in `table?` as well, so other code recognizes it as a table.

-----

1 point by akkartik 4771 days ago | link

I don't understand your example. I think my brain is fried by this conversation. Let me know when you have an example that I can actually run.

-----

1 point by Pauan 4771 days ago | link

What I'm saying is that (my-string "foo") would be equivalent to (posmatch "foo" my-string). I'll try to get message passing working in py-arc.

-----

1 point by Pauan 4771 days ago | link

"The main point of arc is brevity across a range of programs."

Message passing is general... it can apply to all the built-in types, and can also apply to all user-created types. It does increase brevity across a range of programs. You could even write all Arc code in that style, but I don't recommend that. I'm restricting my discussion of message passing to data types because message passing is clearly superior with regard to data types. I make no claims about the superiority of message passing with regard to things other than data types.

I've been using specific examples because as aw mentioned (http://arclanguage.org/item?id=14264) it's important to explain the problem that it solves, and also demonstrate how it solves the problem... but the concept is general.

In any case, since you're demanding runnable code, it's up to me to put my money where my mouth is.

-----