![](/i/fill.gif) |
![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
> LISP works it by (IIRC) passing each token to the "read macros" and
> seeing if any of them modify it, so it has to be distinguishable
> somehow.
> FORTH works it by literally letting you read the input stream,
> as well as calling a specific function when an unparsable word is
> encountered. So in FORTH, a literal works mostly like your quasi-quoting
> scheme, except there's no magic characters at the front or end to say
> "hey, this is quoted."
> Even Erlang has a mechanism to pss the parse tree thru a number of
> routines each of which takes a parse tree and returns a new parse tree.
> It isn't quite as flexible as LISP or FORTH, but it lets you add
> parse-time features pretty easily, like your splice more than anything
Well, there's no law against you writing a Haskell preprocessor in
Haskell. (Though obviously that's not quite as convinient as the
compiler automatically running it for you.)
>> You have to tell the compiler what function to use to parse this
>> stuff, one way or another.
>
> Yeah, but you shouldn't be putting it inline in the stream. You should
> be able to say "anything with < on the front and > at the back should
> parse as an XML tag."
The way Haskell does it has advantages.
1. You can tell that stuff is quoted, and what quoting rule it's using.
(Pointless for something like a hex number, but damned useful for a
complex program with a dozen kinds of AST which you might want to quote.)
2. You can't accidentally write a quoting rule which changes the meaning
of a valid Haskell fragment.
3. The new stuff can have completely different parsing rules to Haskell.
(Presumably the Lisp, Forth and Erlang methods can't do that.)
If you could write XML tags literally, then an expression like "if x<y
then if y>z then..." would suddenly parse as an XML tag, which would be
a Very Bad Thing. Really, having to explicitly say you're doing weird
stuff isn't so bad.
--
http://blog.orphi.me.uk/
http://www.zazzle.com/MathematicalOrchid*
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
>> Can you come up with names?
>
> Delphi.
I thought that died 10 years ago?
> Object-C.
I thought that died when C++ came along? (Although I hear Apple still
uses it.)
> Ada. D. Simula.
I wasn't aware those were *ever* popular.
> C#. Visual Basic.
VB is OO now?
> Hell, even Fortran is OO for the last 10 years.
People use Fortran? I thought that was only for scientific applications.
(Or am I thinking of Forth?)
> So you having heard of it is what makes it "mainstream"? ;-)
Look at job adverts, or websites which talk about programming. They all
mention C, C++, Java, VB, PHP, Perl, Ruby, Python. A few very new ones
might mention C#. Occasionally you'll hear of Erlang. They don't mention
Fortran or Ada. (Like they don't mention Pascal, Eiffel, Smalltalk or
Haskell.)
>>> As long as you don't have inheritance, it *is* pretty trivial.
>>
>> The synax seemed overly complex and intimidating to me.
>
> http://en.wikipedia.org/wiki/Eiffel_%28programming_language%29#Genericity
>
> Seems to be as straightforward as I remember. Pretty much the simplest
> form of Generics out there.
Not as simple as Haskell, but sure, I guess that is reasonably easy.
>> My point is that even bigints are, technically, finite if executed on
>> a physical machine. But, like I said, I'm sure that's not what you
>> meant. ;-)
>
> But they're not bounded in the language. They aren't fixed precision.
OK, sure. What were we debating again...?
>> Right... so if leaves contain a datum and branches don't... Oh, I
>> suppose you just use a null-pointer instead or something?
>
> Or a flag. Or a leaf that inherits from a branch. Or a union-like
> structure. Or, for an N-ary tree, a list of children that happens to be
> empty. (After all, a binary tree is just an N-ary tree with restrictions
> on what it can hold.)
If you specifically want a binary tree, the simplest and most logical OO
way would be to make leaves and branches different subclasses. (Unless
every node contains a datum, in which case branch should probably be a
subclass of leaf.) But sure, the others are possibilities. (And if you
might want N-ary trees, then presumably you're doing to use a list or
array or something for the children, as you say...)
>> Well anyway, I've never seen anyone implement it that way, but I guess
>> you could.
>
> Yeah, but you wouldn't want to in Haskell.
I meant I've never seen it done like that in an OO language. In Haskell
you'd obviously use an ADT, since this is the intended use case.
> http://blogs.msdn.com/ericlippert/archive/2010/02/04/how-many-passes.aspx
>
> Lots of passes, with about half of them being needed only for new
> features in the parse tree (compared to V1 of C#, for example). In a
> real compiler, it's nowhere near as clearcut. :-)
>
> For example,
>
> """
> Then we run a pass that transforms expression trees into the sequence of
> factory method calls necessary to create the expression trees at runtime.
>
> Then we run a pass that rewrites all nullable arithmetic into code that
> tests for HasValue, and so on.
> """
>
> Neither of those passes makes sense before you've added the feature to
> the parse tree data as well.
I'm not quite comprehending the point you're trying to make.
My point is that something like a parse tree usually doesn't need to be
dynamically extensible. If you make an extension to the language, you
typically need to rewrite all the code for processing the parse tree
anyway, so the fact that it's monolithic isn't too much of an issue.
> You're not building real systems.
That's what SHE said...
> And you can do all that in Smalltalk too. But OK, Javascript has less of
> a "class" concept than Smalltalk does.
We are in agreement.
>> In Smalltalk, object fields are accessible only from inside the object.
>
> Not really true. You can use reflection-type stuff to get to them, such
> as in the debugger.
And you can take a C++ program and use pointer arithmetic to access
private member variables. Does that mean C++ doesn't provide encapsulation?
> http://www.devx.com/getHelpOn/10MinuteSolution/16467/0/page/5
"Omitting the 'this' keyword makes the variables private to the object.
The 'var' keyword makes the property local (each object instance gets
its own copy of the variable)."
Well, that's news to me...
>> What's a closure?
>
> It's the value that a lambda expression returns. A "new" statement
> returns an instance, a lambda expression returns a closure.
I still don't really understand.
>>> Bzzzt. You just don't know javascript very well.
>>
>
> function foo() {...}
>
> is the same as
>
> window["foo"] = Function(){...}
OK. So in what way does this mean that "functions are not first-class"?
>>> I didn't say nobody is using it. I said you don't have to support it.
>> Ah, right. Well, don't tell that to the Industrial Haskell Group. ;-)
>
> OK. But the language designers don't count that as "success" and don't
> mind breaking it?
As I said, avoiding success so that they don't have to keep things
stable actually went out the window some years ago in reality. Most
people now *want* Haskell to succeed. (Not that I think it will...)
> I guess if you're using Haskell you just keep the
> version you're using around as long as you need it.
Well, there's always that possibility, it's true.
(You could also write a compiler or interpretter yourself too. The spec
is open...)
>> Does anyone "have to" support Java?
>
> Sure.
Oh. Really?
I can imagine there are product written in Java that somebody has to
support, or that there are Java compilers that somebody has to support.
But the Java language itself?
--
http://blog.orphi.me.uk/
http://www.zazzle.com/MathematicalOrchid*
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
>>> which is obviously a hell of a lot longer.
>>
>> Yet, oddly enough, will work on things that *aren't lists*. That's the
>> point. :-)
>
> Well, you can pattern match on the size of the container (presuming you
> have a polymorphic "size" function to get this). It won't be quite as
> neat though, obviously.
What was the original?
case list of
[[x], [y,_], [z,_,_]] -> x+y+z
_ -> 0
If you want it to work for other containers, you're going to have to do
something like
case size c of
3 -> case (size (c ! 0), size (c ! 1), size (c ! 2)) of
(1, 2, 3) -> (c ! 0 ! 0) + (c ! 1 ! 0) + (c ! 2 ! 0)
_ -> 0
_ -> 0
Which isn't nearly as nice.
> Secondly, there's actually an experimental extension to Haskell called
> "view patterns" which allow you to create sort-of "user defined pattern
> matching". This fixes this exact problem. (And a couple of others.)
No, apparently it doesn't. It just lets me write
case c of
(size -> 3) -> ...
instead of
case size c of
3 -> ...
How dissappointing...
--
http://blog.orphi.me.uk/
http://www.zazzle.com/MathematicalOrchid*
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Orchid XP v8 wrote:
> The way Haskell does it has advantages.
No question.
> 1. You can tell that stuff is quoted, and what quoting rule it's using.
Trivially true of LISP and FORTH, too. LISP syntax is so simple it's hard
not to know what you're quoting, and in FORTH *everything* works that way,
including all the "normal" stuff.
> 2. You can't accidentally write a quoting rule which changes the meaning
> of a valid Haskell fragment.
Yeah. That's the only thing you *can* do in Erlang, which is kind of odd.
> 3. The new stuff can have completely different parsing rules to Haskell.
> (Presumably the Lisp, Forth and Erlang methods can't do that.)
Erlang, no, because it's already parsed when you get it. FORTH and LISP,
yes, it's exactly the point of it. If you can read arbitrary amount of
input off the input file as you're compiling, you can pretty much completely
change the parsing rules.
Of course, the parsing rule for FORTH is "read up to the next whitespace,
then run that function. Repeat." So the whole point of FORTH is that there
isn't any syntax beyond that defined by the libraries. (For example, the
function to define functions, and the "if" statement, are both library
routines.) It can make things rough, tho.
> If you could write XML tags literally, then an expression like "if x<y
> then if y>z then..." would suddenly parse as an XML tag, which would be
> a Very Bad Thing. Really, having to explicitly say you're doing weird
> stuff isn't so bad.
Yeah, that was just an example I saw. Obviously you'd have to take care. I
haven't used Erlang enough to understand the subtleties of its mechanisms.
--
Darren New, San Diego CA, USA (PST)
The question in today's corporate environment is not
so much "what color is your parachute?" as it is
"what color is your nose?"
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Orchid XP v8 <voi### [at] dev null> wrote:
> case size c of
> 3 -> case (size (c ! 0), size (c ! 1), size (c ! 2)) of
> (1, 2, 3) -> (c ! 0 ! 0) + (c ! 1 ! 0) + (c ! 2 ! 0)
> _ -> 0
> _ -> 0
I don't know why, but I got an irresistible urge to write some faux haskell
after seeing that.
case closed in d by
x -> case (open, not!, closed, yes!, 2) because
(1, 2, 3) -> (one, two, three) + x
hence -> yes
hence -> no
To me, it makes exactly as much sense. :P
--
- Warp
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Orchid XP v8 wrote:
>> Ada. D. Simula.
> I wasn't aware those were *ever* popular.
Ada still goes strong in the areas it is designed for, like safety-critical
firmware.
>> C#. Visual Basic.
> VB is OO now?
It always was. Certainly VB.NET is.
>> Hell, even Fortran is OO for the last 10 years.
> People use Fortran? I thought that was only for scientific applications.
And scientists aren't people?
> Look at job adverts, or websites which talk about programming.
That's not "mainstream", that's "popular". :-)
> If you specifically want a binary tree, the simplest and most logical OO
> way would be to make leaves and branches different subclasses.
Not especially. What about a branch with only one child node? Is that a leaf
or a branch? And what's the value in the second branch?
And yes, even if leaves and branches are separate classes, it doesn't mean
that they both aren't of type "treenode", or the leaf could be a subclass of
branch or vice versa.
> I meant I've never seen it done like that in an OO language.
You've never seen a N-ary tree in an OO language that used the same class
for branches and leaves? Wow.
> My point is that something like a parse tree usually doesn't need to be
> dynamically extensible. If you make an extension to the language, you
> typically need to rewrite all the code for processing the parse tree
> anyway, so the fact that it's monolithic isn't too much of an issue.
I disagree. The whole point of giving you the list of passes was showing you
how modular each pass can be, as well as showing you how modular each parse
node type needs to be.
> And you can take a C++ program and use pointer arithmetic to access
> private member variables. Does that mean C++ doesn't provide encapsulation?
Yes.
>>> What's a closure?
>>
>> It's the value that a lambda expression returns. A "new" statement
>> returns an instance, a lambda expression returns a closure.
>
> I still don't really understand.
What is this?
(lambda (x) (x + 1))
It's a lambda expression.
y = (lambda (x) (x + 1))
What is y? It's a closure.
>> window["foo"] = Function(){...}
> OK. So in what way does this mean that "functions are not first-class"?
I didn't say it did. I said that everything in Javascript is an object.
There are no functions unassociated with a corresponding instance.
OK, you said
> The difference is that Haskell functions work on data, while Smalltalk
only has objects. In other words, you can't invoke a function without
knowing what object that "function" is a method of. (This is also the case
for Javascript, btw.)
I wasn't sure what "this is also the case for javascript" meant, but I
thought you meant you can invoke a function without knowing what object it
is a method of. That isn't true of Javascript, altho there is a top-level
object that serves as a global namespace.
> As I said, avoiding success so that they don't have to keep things
> stable actually went out the window some years ago in reality. Most
> people now *want* Haskell to succeed. (Not that I think it will...)
Fair enough.
> I can imagine there are product written in Java that somebody has to
> support, or that there are Java compilers that somebody has to support.
> But the Java language itself?
Well, no, there's nobody who has to support the spec, as such. I meant there
are major systems where someone is paid to make sure the Java it's based on
keeps working.
--
Darren New, San Diego CA, USA (PST)
The question in today's corporate environment is not
so much "what color is your parachute?" as it is
"what color is your nose?"
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
>> 3. The new stuff can have completely different parsing rules to
>> Haskell. (Presumably the Lisp, Forth and Erlang methods can't do that.)
>
> Erlang, no, because it's already parsed when you get it. FORTH and LISP,
> yes, it's exactly the point of it. If you can read arbitrary amount of
> input off the input file as you're compiling, you can pretty much
> completely change the parsing rules.
The way you said "take each token and pass it through a macro" made it
sound like the input stream gets tokenised first - which means if what
you want to quote has different ideas about what constitutes a "token",
you've got a problem.
>> If you could write XML tags literally, then an expression like "if x<y
>> then if y>z then..." would suddenly parse as an XML tag, which would
>> be a Very Bad Thing. Really, having to explicitly say you're doing
>> weird stuff isn't so bad.
>
> Yeah, that was just an example I saw. Obviously you'd have to take care.
> I haven't used Erlang enough to understand the subtleties of its
> mechanisms.
Square enuf.
--
http://blog.orphi.me.uk/
http://www.zazzle.com/MathematicalOrchid*
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Orchid XP v8 wrote:
> The way you said "take each token and pass it through a macro" made it
> sound like the input stream gets tokenised first
It gets tokenized one token at a time. Otherwise, how would your "macro" be
able to read the input? I'm not saying "it looks at the already-parsed
input". I'm saying "it invokes the read() function on stdin to consume input
that was sent to the compiler". The funky syntax is never seen by the
tokenizer (in FORTH and LISP).
--
Darren New, San Diego CA, USA (PST)
The question in today's corporate environment is not
so much "what color is your parachute?" as it is
"what color is your nose?"
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Warp wrote:
> Orchid XP v8 <voi### [at] dev null> wrote:
>> case size c of
>> 3 -> case (size (c ! 0), size (c ! 1), size (c ! 2)) of
>> (1, 2, 3) -> (c ! 0 ! 0) + (c ! 1 ! 0) + (c ! 2 ! 0)
>> _ -> 0
>> _ -> 0
>
> I don't know why, but I got an irresistible urge to write some faux haskell
> after seeing that.
>
> case closed in d by
> x -> case (open, not!, closed, yes!, 2) because
> (1, 2, 3) -> (one, two, three) + x
> hence -> yes
> hence -> no
>
> To me, it makes exactly as much sense. :P
I think c ! 2 is the third element of c, not unlike c[2].
switch (size(c)) {
case 3:
switch (size(c[0]), size(c[1]), size(c[2])) {
case (1,2,3):
return c[0][0] + c[1][0] + c[2][0];
default:
return 0;
}
default:
return 0;
}
It's not *that* hard to figure out. :-)
You should look into playing around with a completely different kind of
programming language not based on C. Erlang or APL or something like that.
--
Darren New, San Diego CA, USA (PST)
The question in today's corporate environment is not
so much "what color is your parachute?" as it is
"what color is your nose?"
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Darren New wrote:
> Orchid XP v8 wrote:
>> The way you said "take each token and pass it through a macro" made it
>> sound like the input stream gets tokenised first
>
> It gets tokenized one token at a time. Otherwise, how would your "macro"
> be able to read the input? I'm not saying "it looks at the
> already-parsed input". I'm saying "it invokes the read() function on
> stdin to consume input that was sent to the compiler". The funky syntax
> is never seen by the tokenizer (in FORTH and LISP).
Tokenising isn't parsing; it's just the initial part where you split the
input into tokens. Thing is, each language has different ideas about
what a "token" is...
Obviously I'm never going to use Lisp or Forth, never mind macros. I'm
just mildly curious to know whether you can implement your own
tokenising rules or not.
--
http://blog.orphi.me.uk/
http://www.zazzle.com/MathematicalOrchid*
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |