Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #74191 > unrolled thread
| Started by | "Rick C. Hodgin" <rick.c.hodgin@gmail.com> |
|---|---|
| First post | 2015-10-29 12:10 -0700 |
| Last post | 2015-10-30 04:01 -0700 |
| Articles | 20 on this page of 67 — 12 participants |
Back to article view | Back to comp.lang.c
CAlive utility casks for arbitrary code injection as needed "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-10-29 12:10 -0700
Re: CAlive utility casks for arbitrary code injection as needed Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-10-29 20:05 +0000
Re: CAlive utility casks for arbitrary code injection as needed Barry Schwarz <schwarzb@dqel.com> - 2015-10-29 14:36 -0700
Re: CAlive utility casks for arbitrary code injection as needed asetofsymbols@gmail.com - 2015-10-29 14:55 -0700
Re: CAlive utility casks for arbitrary code injection as needed "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-10-29 15:46 -0700
Re: CAlive utility casks for arbitrary code injection as needed Barry Schwarz <schwarzb@dqel.com> - 2015-10-29 18:17 -0700
Re: CAlive utility casks for arbitrary code injection as needed Bartc <bc@freeuk.com> - 2015-10-29 21:48 +0000
Re: CAlive utility casks for arbitrary code injection as needed "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-10-29 16:00 -0700
Re: CAlive utility casks for arbitrary code injection as needed Ian Collins <ian-news@hotmail.com> - 2015-10-30 14:25 +1300
Re: CAlive utility casks for arbitrary code injection as needed "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-10-29 18:41 -0700
Re: CAlive utility casks for arbitrary code injection as needed Philip Lantz <prl@canterey.us> - 2015-10-29 21:51 -0700
Re: CAlive utility casks for arbitrary code injection as needed gazelle@shell.xmission.com (Kenny McCormack) - 2015-10-30 13:07 +0000
Re: CAlive utility casks for arbitrary code injection as needed Philip Lantz <prl@canterey.us> - 2015-11-01 11:45 -0800
Re: CAlive utility casks for arbitrary code injection as needed Ian Collins <ian-news@hotmail.com> - 2015-10-30 20:34 +1300
Re: CAlive utility casks for arbitrary code injection as needed Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-10-30 02:09 -0700
Re: CAlive utility casks for arbitrary code injection as needed David Brown <david.brown@hesbynett.no> - 2015-10-30 11:12 +0100
Re: CAlive utility casks for arbitrary code injection as needed Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-10-30 12:03 +0000
Re: CAlive utility casks for arbitrary code injection as needed gazelle@shell.xmission.com (Kenny McCormack) - 2015-10-30 13:16 +0000
Re: CAlive utility casks for arbitrary code injection as needed David Brown <david.brown@hesbynett.no> - 2015-10-30 14:22 +0100
Re: CAlive utility casks for arbitrary code injection as needed Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-10-30 08:54 -0700
Re: CAlive utility casks for arbitrary code injection as needed Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-10-30 16:12 +0000
Re: CAlive utility casks for arbitrary code injection as needed "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-10-30 09:32 -0700
Re: CAlive utility casks for arbitrary code injection as needed Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-10-30 09:57 -0700
Re: CAlive utility casks for arbitrary code injection as needed "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-10-30 10:16 -0700
Re: CAlive utility casks for arbitrary code injection as needed Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-10-30 18:33 +0000
Re: CAlive utility casks for arbitrary code injection as needed David Brown <david.brown@hesbynett.no> - 2015-10-30 22:28 +0100
Re: CAlive utility casks for arbitrary code injection as needed Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-10-30 23:03 +0000
Re: CAlive utility casks for arbitrary code injection as needed Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-10-31 01:35 -0700
Re: CAlive utility casks for arbitrary code injection as needed Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-10-31 11:39 +0000
Re: CAlive utility casks for arbitrary code injection as needed Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-10-31 12:04 -0700
Re: CAlive utility casks for arbitrary code injection as needed "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-10-31 17:56 -0700
Re: CAlive utility casks for arbitrary code injection as needed Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-11-01 03:06 -0800
Re: CAlive utility casks for arbitrary code injection as needed "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-10-30 09:28 -0700
Re: CAlive utility casks for arbitrary code injection as needed "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-10-30 04:24 -0700
Re: CAlive utility casks for arbitrary code injection as needed David Brown <david.brown@hesbynett.no> - 2015-10-30 13:04 +0100
Re: CAlive utility casks for arbitrary code injection as needed "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-10-30 06:18 -0700
Re: CAlive utility casks for arbitrary code injection as needed David Brown <david.brown@hesbynett.no> - 2015-10-30 16:23 +0100
Re: CAlive utility casks for arbitrary code injection as needed "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-10-30 09:25 -0700
Re: CAlive utility casks for arbitrary code injection as needed gazelle@shell.xmission.com (Kenny McCormack) - 2015-10-30 16:47 +0000
Re: CAlive utility casks for arbitrary code injection as needed "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-10-30 10:13 -0700
Re: CAlive utility casks for arbitrary code injection as needed "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-10-30 10:56 -0700
Re: CAlive utility casks for arbitrary code injection as needed David Brown <david.brown@hesbynett.no> - 2015-10-31 17:04 +0100
Re: CAlive utility casks for arbitrary code injection as needed "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-10-31 09:48 -0700
Re: CAlive utility casks for arbitrary code injection as needed gazelle@shell.xmission.com (Kenny McCormack) - 2015-10-31 17:51 +0000
Re: CAlive utility casks for arbitrary code injection as needed David Brown <david.brown@hesbynett.no> - 2015-11-01 00:10 +0100
Re: CAlive utility casks for arbitrary code injection as needed "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-10-31 17:11 -0700
Re: CAlive utility casks for arbitrary code injection as needed David Brown <david.brown@hesbynett.no> - 2015-11-01 15:24 +0100
Re: CAlive utility casks for arbitrary code injection as needed "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-11-01 06:37 -0800
Re: CAlive utility casks for arbitrary code injection as needed David Brown <david.brown@hesbynett.no> - 2015-11-01 21:21 +0100
Re: CAlive utility casks for arbitrary code injection as needed "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-11-01 16:39 -0800
Re: CAlive utility casks for arbitrary code injection as needed David Brown <david.brown@hesbynett.no> - 2015-11-02 02:02 +0100
Re: CAlive utility casks for arbitrary code injection as needed "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-11-01 17:17 -0800
Re: CAlive utility casks for arbitrary code injection as needed raltbos@xs4all.nl (Richard Bos) - 2015-11-02 14:24 +0000
Re: CAlive utility casks for arbitrary code injection as needed "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-11-02 07:46 -0800
Re: CAlive utility casks for arbitrary code injection as needed gazelle@shell.xmission.com (Kenny McCormack) - 2015-11-02 16:30 +0000
Re: CAlive utility casks for arbitrary code injection as needed "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-11-02 08:46 -0800
Re: CAlive utility casks for arbitrary code injection as needed Les Cargill <lcargill99@comcast.com> - 2015-11-02 12:20 -0600
Re: CAlive utility casks for arbitrary code injection as needed "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-11-02 10:23 -0800
Re: CAlive utility casks for arbitrary code injection as needed David Brown <david.brown@hesbynett.no> - 2015-11-02 20:17 +0100
Re: CAlive utility casks for arbitrary code injection as needed Bartc <bc@freeuk.com> - 2015-10-30 01:32 +0000
Re: CAlive utility casks for arbitrary code injection as needed "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-10-29 18:59 -0700
Re: CAlive utility casks for arbitrary code injection as needed Philip Lantz <prl@canterey.us> - 2015-10-29 21:55 -0700
Re: CAlive utility casks for arbitrary code injection as needed gazelle@shell.xmission.com (Kenny McCormack) - 2015-10-30 13:10 +0000
Re: CAlive utility casks for arbitrary code injection as needed Philip Lantz <prl@canterey.us> - 2015-11-01 11:45 -0800
Re: CAlive utility casks for arbitrary code injection as needed Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-10-30 10:55 +0000
Re: CAlive utility casks for arbitrary code injection as needed Philip Lantz <prl@canterey.us> - 2015-10-29 22:00 -0700
Re: CAlive utility casks for arbitrary code injection as needed "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-10-30 04:01 -0700
Page 2 of 4 — ← Prev page 1 [2] 3 4 Next page →
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2015-10-30 16:12 +0000 |
| Message-ID | <87k2q4e3nr.fsf@bsb.me.uk> |
| In reply to | #74328 |
Malcolm McLean <malcolm.mclean5@btinternet.com> writes: <snip> > As far as I see it a cask is a) a reinvention of a lambda function [...] Lambda expressions have two main features: they can bind names, and they have a value which is a function. I've seen no syntax that suggest casks can bind names, and no example that shows casks evaluate to function values. <snip> -- Ben.
[toc] | [prev] | [next] | [standalone]
| From | "Rick C. Hodgin" <rick.c.hodgin@gmail.com> |
|---|---|
| Date | 2015-10-30 09:32 -0700 |
| Message-ID | <a7045d7e-f9b0-46a5-aa8b-d95a8f27dcb6@googlegroups.com> |
| In reply to | #74334 |
On Friday, October 30, 2015 at 12:12:50 PM UTC-4, Ben Bacarisse wrote:
> Malcolm McLean <malcolm.mclean5@btinternet.com> writes:
> <snip>
> > As far as I see it a cask is a) a reinvention of a lambda function [...]
>
> Lambda expressions have two main features: they can bind names, and they
> have a value which is a function. I've seen no syntax that suggest
> casks can bind names,
I'm not sure what binding names means, but [|definition|] casks create
things at their location. In the fif () example above, it was like this:
fif (x == 2 && y == 3)
{
// The full-if statement evaluated every expression, and created
// an implicit local variable called _fif which contains members
// _l1, _l2, ... _lN as needed, indicating the result of each
// logical test
}
By using the definition cask, the names used for _lN can be overridden:
fif ( [|xtest|] x == 2 && [|ytest|] y == 3)
Now, in addition to _fif.l1 and _fifl2 there exists _fif.xtest, and
_fif.ytest.
> and no example that shows casks evaluate to
> function values.
All reference and utility casks evaluate to function values if the last
thing they do is call something which returns a value, AND they are the
only parameter in use at that point. In all other cases, the return
values of casks are discarded, unless they are used within nested casks,
in which case they will fall through and populate the associated
parameters (as CAlive supports multiple return values).
Best regards,
Rick C. Hodgin
[toc] | [prev] | [next] | [standalone]
| From | Malcolm McLean <malcolm.mclean5@btinternet.com> |
|---|---|
| Date | 2015-10-30 09:57 -0700 |
| Message-ID | <3983c689-b700-47d6-83d0-3130771a6f69@googlegroups.com> |
| In reply to | #74339 |
On Friday, October 30, 2015 at 4:32:55 PM UTC, Rick C. Hodgin wrote: > On Friday, October 30, 2015 at 12:12:50 PM UTC-4, Ben Bacarisse wrote: > > Malcolm McLean <malcolm.mclean5@btinternet.com> writes: > > <snip> > > > As far as I see it a cask is a) a reinvention of a lambda function [...] > > > > Lambda expressions have two main features: they can bind names, and they > > have a value which is a function. I've seen no syntax that suggest > > casks can bind names, > > I'm not sure what binding names means, but [|definition|] casks create > things at their location. > Lambda expressions take a snapshot of the names in scope. They can then be called outside of that environment, even if the function where the lambda was declared has gone out of scope. So "cask" is a nice name for a lambda variant. Think of it as closing up the names, and keeping them safe in a container, to use them when opened.
[toc] | [prev] | [next] | [standalone]
| From | "Rick C. Hodgin" <rick.c.hodgin@gmail.com> |
|---|---|
| Date | 2015-10-30 10:16 -0700 |
| Message-ID | <25ca4ab7-99ee-4b4f-92dd-db66b9edfba7@googlegroups.com> |
| In reply to | #74344 |
On Friday, October 30, 2015 at 12:57:50 PM UTC-4, Malcolm McLean wrote: > On Friday, October 30, 2015 at 4:32:55 PM UTC, Rick C. Hodgin wrote: > > On Friday, October 30, 2015 at 12:12:50 PM UTC-4, Ben Bacarisse wrote: > > > Malcolm McLean <malcolm.mclean5@btinternet.com> writes: > > > <snip> > > > > As far as I see it a cask is a) a reinvention of a lambda function [...] > > > > > > Lambda expressions have two main features: they can bind names, and they > > > have a value which is a function. I've seen no syntax that suggest > > > casks can bind names, > > > > I'm not sure what binding names means, but [|definition|] casks create > > things at their location. > > > Lambda expressions take a snapshot of the names in scope. They can then be > called outside of that environment, even if the function where the lambda was > declared has gone out of scope. > So "cask" is a nice name for a lambda variant. Think of it as closing up the names, > and keeping them safe in a container, to use them when opened. I have created a concept called "thisCode" for that ability. I do not have it incorporated into CAlive because the references to things which are not dynamically allocated are not conveyed in CAlive, but it exists in VXB++ and VXB. In those languages, it uses the thisCode reference sort of like a "this" reference which can be passed as a pointer to the environment from whichi it was derived, allowing access to all resources from that relative location. Best regards, Rick C. Hodgin
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2015-10-30 18:33 +0000 |
| Message-ID | <87eggcdx4v.fsf@bsb.me.uk> |
| In reply to | #74344 |
Malcolm McLean <malcolm.mclean5@btinternet.com> writes: > On Friday, October 30, 2015 at 4:32:55 PM UTC, Rick C. Hodgin wrote: >> On Friday, October 30, 2015 at 12:12:50 PM UTC-4, Ben Bacarisse wrote: >> > Malcolm McLean <malcolm.mclean5@btinternet.com> writes: >> > <snip> >> > > As far as I see it a cask is a) a reinvention of a lambda function [...] >> > >> > Lambda expressions have two main features: they can bind names, and they >> > have a value which is a function. I've seen no syntax that suggest >> > casks can bind names, >> >> I'm not sure what binding names means, but [|definition|] casks create >> things at their location. >> > Lambda expressions take a snapshot of the names in scope. They can > then be called outside of that environment, even if the function where > the lambda was declared has gone out of scope. So "cask" is a nice > name for a lambda variant. They still appear to lack all the key attributes of a lambda (for example Rick stated that they don't evaluate to function values). Unless almost everything that is code fits your meaning of "lambda variant" they don't seem to fit either. <snip> -- Ben.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2015-10-30 22:28 +0100 |
| Message-ID | <n10n8u$91e$1@dont-email.me> |
| In reply to | #74354 |
On 30/10/15 19:33, Ben Bacarisse wrote: > Malcolm McLean <malcolm.mclean5@btinternet.com> writes: > >> On Friday, October 30, 2015 at 4:32:55 PM UTC, Rick C. Hodgin wrote: >>> On Friday, October 30, 2015 at 12:12:50 PM UTC-4, Ben Bacarisse wrote: >>>> Malcolm McLean <malcolm.mclean5@btinternet.com> writes: >>>> <snip> >>>>> As far as I see it a cask is a) a reinvention of a lambda function [...] >>>> >>>> Lambda expressions have two main features: they can bind names, and they >>>> have a value which is a function. I've seen no syntax that suggest >>>> casks can bind names, >>> >>> I'm not sure what binding names means, but [|definition|] casks create >>> things at their location. >>> >> Lambda expressions take a snapshot of the names in scope. They can >> then be called outside of that environment, even if the function where >> the lambda was declared has gone out of scope. So "cask" is a nice >> name for a lambda variant. > > They still appear to lack all the key attributes of a lambda (for > example Rick stated that they don't evaluate to function values). > Unless almost everything that is code fits your meaning of "lambda > variant" they don't seem to fit either. > I think the point of the cask/lambda comparison is that many of the things that can be done with casks could be done with lambdas - not that casks can do all that lambdas can do. (The "adhoc" functions are closer to being able to duplicate lambdas.)
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2015-10-30 23:03 +0000 |
| Message-ID | <8737wsdknj.fsf@bsb.me.uk> |
| In reply to | #74370 |
David Brown <david.brown@hesbynett.no> writes: > On 30/10/15 19:33, Ben Bacarisse wrote: >> Malcolm McLean <malcolm.mclean5@btinternet.com> writes: >> >>> On Friday, October 30, 2015 at 4:32:55 PM UTC, Rick C. Hodgin wrote: >>>> On Friday, October 30, 2015 at 12:12:50 PM UTC-4, Ben Bacarisse wrote: >>>>> Malcolm McLean <malcolm.mclean5@btinternet.com> writes: >>>>> <snip> >>>>>> As far as I see it a cask is a) a reinvention of a lambda function [...] >>>>> >>>>> Lambda expressions have two main features: they can bind names, and they >>>>> have a value which is a function. I've seen no syntax that suggest >>>>> casks can bind names, >>>> >>>> I'm not sure what binding names means, but [|definition|] casks create >>>> things at their location. >>>> >>> Lambda expressions take a snapshot of the names in scope. They can >>> then be called outside of that environment, even if the function where >>> the lambda was declared has gone out of scope. So "cask" is a nice >>> name for a lambda variant. >> >> They still appear to lack all the key attributes of a lambda (for >> example Rick stated that they don't evaluate to function values). >> Unless almost everything that is code fits your meaning of "lambda >> variant" they don't seem to fit either. > > I think the point of the cask/lambda comparison is that many of the > things that can be done with casks could be done with lambdas - not > that casks can do all that lambdas can do. That may well be true, but I was not commenting on a remark that lambdas can do much or all of what casks can do, I was commenting on two remarks said something else entirely: "a cask is [...] a reinvention of a lambda" and "'cask' is a nice name for a lambda variant". The first appears to be flat-out wrong, and the second is only correct if "lambda variant" is used to mean "small subset of a lambda's attributes". <snip> -- Ben.
[toc] | [prev] | [next] | [standalone]
| From | Malcolm McLean <malcolm.mclean5@btinternet.com> |
|---|---|
| Date | 2015-10-31 01:35 -0700 |
| Message-ID | <4ff8e544-081f-4142-a621-f825a387a664@googlegroups.com> |
| In reply to | #74379 |
On Friday, October 30, 2015 at 11:03:30 PM UTC, Ben Bacarisse wrote: > David Brown <david.brown@hesbynett.no> writes: > > That may well be true, but I was not commenting on a remark that lambdas > can do much or all of what casks can do, I was commenting on two remarks > said something else entirely: "a cask is [...] a reinvention of a > lambda" and "'cask' is a nice name for a lambda variant". The first > appears to be flat-out wrong, and the second is only correct if "lambda > variant" is used to mean "small subset of a lambda's attributes". > The purpose of a cask is to perform enclosure, surely? It's a better name than "lambda", which as far as I can tell is just an arbitrary Greek letter.
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2015-10-31 11:39 +0000 |
| Message-ID | <877fm3clna.fsf@bsb.me.uk> |
| In reply to | #74412 |
Malcolm McLean <malcolm.mclean5@btinternet.com> writes:
> On Friday, October 30, 2015 at 11:03:30 PM UTC, Ben Bacarisse wrote:
>> David Brown <david.brown@hesbynett.no> writes:
>>
>> That may well be true, but I was not commenting on a remark that lambdas
>> can do much or all of what casks can do, I was commenting on two remarks
>> said something else entirely: "a cask is [...] a reinvention of a
>> lambda" and "'cask' is a nice name for a lambda variant". The first
>> appears to be flat-out wrong, and the second is only correct if "lambda
>> variant" is used to mean "small subset of a lambda's attributes".
>>
> The purpose of a cask is to perform enclosure, surely?
A {...} block also encloses code. Why do you think a "cask" is like a
function-valued expression rather being than a block of code? I don't
see anything in the examples to suggest that "casks" are like anonymous
functions.
> It's a
> better name than "lambda", which as far as I can tell is just
> an arbitrary Greek letter.
X can't be a better name for Y if X really means Z. If a "cask" really
turns out to be a function expression, I'll agree -- the name is better
than lambda -- but there is currently no evidence that a "cask" is a
function expression. I think it's a name for something that neither of
us understands (but if you do know what they are, please explain them --
Rick can't).
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | Malcolm McLean <malcolm.mclean5@btinternet.com> |
|---|---|
| Date | 2015-10-31 12:04 -0700 |
| Message-ID | <b278c0a3-f34e-40a1-be7f-373d1261bcd8@googlegroups.com> |
| In reply to | #74422 |
On Saturday, October 31, 2015 at 11:39:34 AM UTC, Ben Bacarisse wrote:
> Malcolm McLean <malcolm.mclean5@btinternet.com> writes:
>
> > On Friday, October 30, 2015 at 11:03:30 PM UTC, Ben Bacarisse wrote:
> >> David Brown <david.brown@hesbynett.no> writes:
> >>
> >> That may well be true, but I was not commenting on a remark that lambdas
> >> can do much or all of what casks can do, I was commenting on two remarks
> >> said something else entirely: "a cask is [...] a reinvention of a
> >> lambda" and "'cask' is a nice name for a lambda variant". The first
> >> appears to be flat-out wrong, and the second is only correct if "lambda
> >> variant" is used to mean "small subset of a lambda's attributes".
> >>
> > The purpose of a cask is to perform enclosure, surely?
>
> A {...} block also encloses code. Why do you think a "cask" is like a
> function-valued expression rather being than a block of code? I don't
> see anything in the examples to suggest that "casks" are like anonymous
> functions.
>
> > It's a
> > better name than "lambda", which as far as I can tell is just
> > an arbitrary Greek letter.
>
> X can't be a better name for Y if X really means Z. If a "cask" really
> turns out to be a function expression, I'll agree -- the name is better
> than lambda -- but there is currently no evidence that a "cask" is a
> function expression. I think it's a name for something that neither of
> us understands (but if you do know what they are, please explain them --
> Rick can't).
>
It's not clear to me whether "casks" are meant to capture code for
execution later, or if they merely package it up for display in a GUI
when the mouse hovers over the cask symbol.
They might well have different scoping rules to lambdas - since they
have been derived independently, you'd expect some differences.
But neither lambda calculus nor the cask was my personal invention,
I'm not especially well qualified to comment, particularly when the
inventer of the cask is here.
[toc] | [prev] | [next] | [standalone]
| From | "Rick C. Hodgin" <rick.c.hodgin@gmail.com> |
|---|---|
| Date | 2015-10-31 17:56 -0700 |
| Message-ID | <98f80360-d531-47dc-8250-4a9f93a5da2f@googlegroups.com> |
| In reply to | #74472 |
On Saturday, October 31, 2015 at 3:04:44 PM UTC-4, Malcolm McLean wrote:
> On Saturday, October 31, 2015 at 11:39:34 AM UTC, Ben Bacarisse wrote:
> > Malcolm McLean <malcolm.mclean5@btinternet.com> writes:
> >
> > > On Friday, October 30, 2015 at 11:03:30 PM UTC, Ben Bacarisse wrote:
> > >> David Brown <david.brown@hesbynett.no> writes:
> > >>
> > >> That may well be true, but I was not commenting on a remark that lambdas
> > >> can do much or all of what casks can do, I was commenting on two remarks
> > >> said something else entirely: "a cask is [...] a reinvention of a
> > >> lambda" and "'cask' is a nice name for a lambda variant". The first
> > >> appears to be flat-out wrong, and the second is only correct if "lambda
> > >> variant" is used to mean "small subset of a lambda's attributes".
> > >>
> > > The purpose of a cask is to perform enclosure, surely?
> >
> > A {...} block also encloses code. Why do you think a "cask" is like a
> > function-valued expression rather being than a block of code? I don't
> > see anything in the examples to suggest that "casks" are like anonymous
> > functions.
> >
> > > It's a
> > > better name than "lambda", which as far as I can tell is just
> > > an arbitrary Greek letter.
> >
> > X can't be a better name for Y if X really means Z. If a "cask" really
> > turns out to be a function expression, I'll agree -- the name is better
> > than lambda -- but there is currently no evidence that a "cask" is a
> > function expression. I think it's a name for something that neither of
> > us understands (but if you do know what they are, please explain them --
> > Rick can't).
> >
> It's not clear to me whether "casks" are meant to capture code for
> execution later, or if they merely package it up for display in a GUI
> when the mouse hovers over the cask symbol.
Casks are fully expanded forms in source code. They can have return
values, function names, and parameters when in the form of a
(|reference|) cask, or a ~|utility|~ cask:
(||return|function_name|param1, param2, param3, ...||)
~||return|function_name|param1, param2, param3, ...||~
(|reference|) casks are used to call other things (functions, adhocs,
member functions), whereas ~|utility|~ casks can do that, but they
are designed more for injecting whatever code where you want it to
be:
~|x = 5; printf("%d\n", my_function(x));|~
And then to simplify them in the GUI editor, there are additional
parts which can be added:
(||return|function_name|param1, param2, param3, ...||).name(update_total)
~|x = 5; printf("%d\n", my_function(x));|~.name(debug_print)
So that in the GUI editor they will appear in their short forms:
(o|update_total|o)
~|debug_print|~
Since casks are enclosed expressions, they can be inserted anywhere in
code. If they are inserted before a parameter is used, they will be
called before that parameter is put on the stack. If they're inserted
after, then they'll be called after it's on the stack. If they're
inserted before a logic test, then they'll be called before the test
is made. If they're inserted after a logic test, then they'll be called
after the logic test is made (if the logic then reached that far, for
example).
And so on...
-----
There are two more types of casks:
[|definition|]
<|logic|>
[|definition|] casks alter the way things are defined. You can put
in overrides, or augments to their definition. An example people
might be aware of would be:
char p [|const|];
// same as "const char p;"
Why would someone do this? Casks show up graphically in the editor,
and it may be more eye catching to see something which looks like this
in the GUI editor:
[char p];
Where the coloring of the "char p" portion is highlighted so that it
conveys the const nature without the keyword const. That's just an
example, by the way, but one I will probably include, along with other
similar ones.
-----
<|logic|> casks respond to true or false conditions set by flow control
operators, or they can inject their own as the left-most place in the
cask, then acting like a ((cond) ? iftrue : iffalse) expression:
<||cond|iftrue|iffalse||>
There are specific types, however, which are called META and MEFA, for
true and false, respectively:
<|meta|iftrue||>
<|mefa|iffalse||>
In these cases, these casks can be added to expressions and then will
signal the code based on the logic condition result:
if (x == 5 <|meta|iftrue||> <|meta|iffalse||>)
{
// Normal code here
}
In this example, the equivalent code would be:
llTest = (x == 5);
if (!llTest)
{
iffalse();
} else {
iftrue();
// Normal code here
}
And they can be inserted anywhere there are logic tests.
There are two other types of logic cask which follows the meta/mefa form
that I haven't introduced yet. They relate to new features of CAlive:
<|meia|> // Inquiry signal handler casks
<|mema|> // Message handler casks
If you think a line might throw an exception, which is called an inquiry
in CAlive, then you can attach a <|meia|> logic cask to it, and when
the inquiry happens, it will trigger that code:
some_function() <|meia|inquiry_handler||>;
Now, if something in some_function() or lower triggers an inquiry, it
will come back to this point and call the inquiry_handler() function.
And if there are specific types, then it can be moved to the left-most
slot for the testing:
some_function() <||_OUT_OF_MEMORY|meia|inquiry_handler_memory||>
<||_FLOATING_POINT|meia|inquiry_handler_fp||>
<|meia|inquiry_handler_default||>;
In this case, those two types of inquirys are handled explicitly, with
all others falling through to the default handler. If the default
handler wasn't specified, then other inquirys would not be handld here.
And <|meia|> casks can be inserted anywhere. I also introduce a special
flow control block which is similar to try..catch which handles inquiries.
-----
<|mema|> are message hander casks. It is a new CAlive feature to allow
not only a return value to be returned, but also a message. Messages
are available specifically to trigger <|mema|> casks, and are ignored
otherwise. Messages can return any combination of an integer, pointer
to text, or a pointer to any other thing, as int num, char* msg, and
void* p members.
void handler_message(char* p, int i)
{
printf("%s on %d\n", p, i);
}
some_function() <|mema|handler_message(mema.msg, mema.num)||>;
void some_function(void)
{
if (date_is_monday_thru_friday)
return message "Hi, mom!", day_of_week_number;
}
In this case, the message would be returned if the logic test passed,
and it would trigger the handler_message() function only in that case.
By embedding a ~|utility|~ cask within the <|mema|> cask, it then also
becomes possible to handle direct branching based on the returned
message, though this is typically handled through the flow { } blocks,
which I have not yet introduced, though I did introduce them many
months ago.
> They might well have different scoping rules to lambdas - since they
> have been derived independently, you'd expect some differences.
>
> But neither lambda calculus nor the cask was my personal invention,
> I'm not especially well qualified to comment, particularly when the
> inventer of the cask is here.
I doubt this was a help. It's a lot of explanation about things which
to other people aren't real yet. You don't have a tool to sit down
and play with it and re-interpret my wordy explanations into the way
you think... so until then, it will just have to be a curiosity most
likely.
Best regards,
Rick C. Hodgin
[toc] | [prev] | [next] | [standalone]
| From | Malcolm McLean <malcolm.mclean5@btinternet.com> |
|---|---|
| Date | 2015-11-01 03:06 -0800 |
| Message-ID | <ce6fc942-aee7-4a24-9729-524b8d534a4a@googlegroups.com> |
| In reply to | #74512 |
On Sunday, November 1, 2015 at 12:56:21 AM UTC, Rick C. Hodgin wrote:
>
> > It's not clear to me whether "casks" are meant to capture code for
> > execution later, or if they merely package it up for display in a GUI
> > when the mouse hovers over the cask symbol.
>
> Casks are fully expanded forms in source code. They can have return
> values, function names, and parameters when in the form of a
> (|reference|) cask, or a ~|utility|~ cask:
>
> (||return|function_name|param1, param2, param3, ...||)
> ~||return|function_name|param1, param2, param3, ...||~
>
> (|reference|) casks are used to call other things (functions, adhocs,
> member functions), whereas ~|utility|~ casks can do that, but they
> are designed more for injecting whatever code where you want it to
> be:
>
> ~|x = 5; printf("%d\n", my_function(x));|~
>
> > But neither lambda calculus nor the cask was my personal invention,
> > I'm not especially well qualified to comment, particularly when the
> > inventer of the cask is here.
>
> I doubt this was a help. It's a lot of explanation about things which
> to other people aren't real yet. You don't have a tool to sit down
> and play with it and re-interpret my wordy explanations into the way
> you think... so until then, it will just have to be a curiosity most
> likely.
>
I think you need to read up on lambda functions and get au fait with them.
They're very much flavour of the month, and a lot of theoretical work
has been done on them. You don't have to understand it fully to have a
reasonable understanding of the terminology.
I think you'll realise that casks are similar to lambdas, and can probably be
recast or reformulated to make them essentially equivalent. The inventive step
is then a) the cask expands in a GUI to show the source, otherwise hides it,
b) we've got a classification and maybe expansion of the idea, so we've got a
distinction between casks which call subroutines and casks which don't,
casks which can throw exceptions (not allowed in lambda calculus, and in fact
driving coach and horses through the theory, but possibly something to allow
for real programming languages), and casks which can't, casks which are
booleans and designed for flow control and casks which are general-purpose.
Then I think you'd have something really worthwhile to offer, and you'd be
talking the same language as lambdas. Also, I think you'd realise that the
scoping rules, maybe can be changed to make casks more powerful.
[toc] | [prev] | [next] | [standalone]
| From | "Rick C. Hodgin" <rick.c.hodgin@gmail.com> |
|---|---|
| Date | 2015-10-30 09:28 -0700 |
| Message-ID | <b11a9929-3391-4eb0-a63d-15d95bdff9f4@googlegroups.com> |
| In reply to | #74328 |
On Friday, October 30, 2015 at 11:54:47 AM UTC-4, Malcolm McLean wrote: > On Friday, October 30, 2015 at 1:22:50 PM UTC, David Brown wrote: > > > > > > Yes, I'd like to see such an example too. While I know without doubt > > that I would never use CAlive (for a good many reasons), it would be > > nice to see a case where casks really give added value to the language. > > Rick has invested a lot of time and effort in them, and received almost > > completely negative feedback here - it would be nice to see that his > > effort has not been entirely wasted. > > > As far as I see it a cask is a) a reinvention of a lambda function and b) > marked up so the IDE displays or hides the code according to mouse > position. There is more than one type of cask. I doubt they all relate to lambda functions. The full intention of RDC and CAlive is to have an integrated compiler that works together with the IDE to convey things that the developer would desire to know about their code, and the compilation of their code. It is also exclusively within the LiveCode environment, making its integration with the debugger/editor almost a single unit. In fact, it ultimately might be more so a single unit than I currently envision. Best regards, Rick C. Hodgin
[toc] | [prev] | [next] | [standalone]
| From | "Rick C. Hodgin" <rick.c.hodgin@gmail.com> |
|---|---|
| Date | 2015-10-30 04:24 -0700 |
| Message-ID | <bf41c91e-8aac-4fd3-9142-3dc08bd6cef7@googlegroups.com> |
| In reply to | #74233 |
On Friday, October 30, 2015 at 3:34:25 AM UTC-4, Ian Collins wrote:
> Rick C. Hodgin wrote:
> > On Thursday, October 29, 2015 at 9:25:39 PM UTC-4, Ian Collins wrote:
> >> Rick C. Hodgin wrote:
> >>> On Thursday, October 29, 2015 at 5:48:26 PM UTC-4, Bart wrote:
> >>>> Does ~|....|~ denote a bit of code that is not immediately evaluated
> >>>> (maybe like QUOTE in Lisp)?
> >>>
> >>> The ~|utility|~ cask is an arbitrary injection of any code. It will
> >>> be inserted at whatever point you insert the cask in a statement.
> >>> The contents of the utility can contain anything. If it is a larger
> >>> block it will be filled with multi-line content between the ~| and |~
> >>> sides. However, CAlive provides for another feature whenever larger
> >>> bits of code are required. They would typically be used, along with
> >>> the (|reference|) casks, instead of the ~|utility|~ cask:
> >>
> >> If I remember correctly, the last time this topic came up it was
> >> demonstrated that C++ cam already do what you were after.
> >
> > And as I told you back then, and you refused to listen to it, C++
> > cannot do what casks do. Nor a dozen other things I propose in
> > my language.
>
> So provide an example use that C++ can't match. If you are attempting
> to prove the utility of a new idea, you have to show that is is new.
You will see in time. My goals in these posts are to "warm up the
audience" by introducing little bits to chew on over time.
-----
In addition to the (|reference|) and ~|utility|~ casks, I also introduce
the logic cask.
I define two basic types:
<|meta|> called when the result is true
<|mefa|> called when the result is false
As an example of a <|logic|> cask:
adhoc iftrue { printf("true\n"); }
adhoc iffalse { printf("false\n"); }
if (x == 2 <||meta|iftrue|> <||mefa|iffalse|>)
{
// Code goes here
}
switch (x)
{
case 2 <||meta|iftrue|> <||mefa|iffalse|>:
// Code goes here
break;
}
Bear in mind that in the GUI editor, these expressions would be
reduced down to visual forms which look like this until expanded:
if (x == 2 <|iftrue|> <|iffalse|>)
{
// Code goes here
}
switch (x)
{
case 2 <|iftrue|> <|iffalse|>:
// Code goes here
break;
}
And only when some GUI interaction takes place would they be expanded.
It makes them easy to see, easy to manage. They can be grabbed hold
of with the mouse as a single unit and dragged around, etc.
-----
CAlive also introduces the "always_before" and "always_after" code blocks
for various things:
// Note: the [once] syntax below indicates "once" is a keyword that
// is optional, same for [per_call].
while (some_condition)
{
// Code goes here
} always_before [once] [per_call] {
// Code executes before the while loop begins
// If once is applied, then it only executes the first time
// the while loop is traversed throughout the lifetime of
// the program. If per_call is applied, then it will use
// a local flag to determine if it should be called.
} always_after [once] [per_call] {
// Code executes after the while loop exits
// If once is applied, then it only executes the first time
// the while loop is traversed throughout the lifetime of
// the program. If per_call is applied, then it will use
// a local flag to determine if it should be called.
}
-----
CAlive also introduces the "unless" clause:
do {
// Code goes here
} unless (some_test1) {
// Code here will execute upon entry into the block if some_test1
// fails. It can issue a break; or a retry; after setting up the
// runtime environment to try again
break;
} unless (some_test2) {
// More tests can be made
retry [all]; // If all is specified, it retries every test,
// otherwise, it retries only this test and
// then continues on to the next (if any).
} while (some_condition);
// And similarly, always_before and always_after blocks can be added.
In all of the above cases, the code that is inserted in this way so that
it's encapsulated in the place it's used, helping to create self-
documenting code. Things that relate to each other relate to each other
spatially, and not just conceptually. They also convey more of the
meaning inherent in code.
-----
CAlive also allows do loops to have their test clause at the top:
do while {
// Code goes here
// } unless (test) { blocks can go here
}; // semicolon here is optional, and ignored
Best regards,
Rick C. Hodgin
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2015-10-30 13:04 +0100 |
| Message-ID | <n0vm82$djg$1@dont-email.me> |
| In reply to | #74271 |
On 30/10/15 12:24, Rick C. Hodgin wrote:
> On Friday, October 30, 2015 at 3:34:25 AM UTC-4, Ian Collins wrote:
>> Rick C. Hodgin wrote:
>>> On Thursday, October 29, 2015 at 9:25:39 PM UTC-4, Ian Collins wrote:
>>>> Rick C. Hodgin wrote:
>>>>> On Thursday, October 29, 2015 at 5:48:26 PM UTC-4, Bart wrote:
>>>>>> Does ~|....|~ denote a bit of code that is not immediately evaluated
>>>>>> (maybe like QUOTE in Lisp)?
>>>>>
>>>>> The ~|utility|~ cask is an arbitrary injection of any code. It will
>>>>> be inserted at whatever point you insert the cask in a statement.
>>>>> The contents of the utility can contain anything. If it is a larger
>>>>> block it will be filled with multi-line content between the ~| and |~
>>>>> sides. However, CAlive provides for another feature whenever larger
>>>>> bits of code are required. They would typically be used, along with
>>>>> the (|reference|) casks, instead of the ~|utility|~ cask:
>>>>
>>>> If I remember correctly, the last time this topic came up it was
>>>> demonstrated that C++ cam already do what you were after.
>>>
>>> And as I told you back then, and you refused to listen to it, C++
>>> cannot do what casks do. Nor a dozen other things I propose in
>>> my language.
>>
>> So provide an example use that C++ can't match. If you are attempting
>> to prove the utility of a new idea, you have to show that is is new.
>
> You will see in time. My goals in these posts are to "warm up the
> audience" by introducing little bits to chew on over time.
I can see that point, but I think if you don't come up with something
interesting soon your audience will wander away and not bother paying
attention later. I keep hoping you'll come up with something new and
interesting, or some example in which the casks give code that is
clearer, simpler, easier to maintain, or in some other way better than
could be done with existing solutions (C, C++, or extensions in existing
compilers such as gcc, clang or lcc). So far I have been disappointed -
but I haven't yet wandered away.
(Note that although your casks and adhocs can - as far as I have seen -
be replaced by standard C or C++, I strongly disapprove of writing code
in that style. The implementations using lambdas or macros are merely
to show that you don't need to invent casks in order to write bad code.)
>
> -----
> In addition to the (|reference|) and ~|utility|~ casks, I also introduce
> the logic cask.
>
> I define two basic types:
>
> <|meta|> called when the result is true
> <|mefa|> called when the result is false
>
> As an example of a <|logic|> cask:
>
> adhoc iftrue { printf("true\n"); }
> adhoc iffalse { printf("false\n"); }
>
Normal functions, macros, nested functions and lambdas are all
alternative ways to define these "adhoc" functions, though in this
example it is hard to see why you want them to be within the function
rather than file-level statics, but not simply written directly at the
place they are called.
Still, macros are the nearest plain C alternative:
#define iftrue printf("true\n")
#define iffalse printf("false\n")
> if (x == 2 <||meta|iftrue|> <||mefa|iffalse|>)
> {
> // Code goes here
> }
if (x == 2) {
iftrue;
// Code goes here
} else {
iffalse;
}
Clear, simple, and obvious. Your casks add nothing.
>
> switch (x)
> {
> case 2 <||meta|iftrue|> <||mefa|iffalse|>:
> // Code goes here
> break;
> }
The "iftrue" part can go directly in the case, just before "Code goes
here". Again, the standard C is clearer and simpler than the casks.
The "iffalse" part is harder - it is far from clear how it should
interact with other code. Should it be run for all cases other than 2?
Should it be run before or after "iftrue" parts for other cases?
Should that depend on whether those cases are before or after case 2?
Even if you have a single answer to that question, it is not going to be
obvious when used - and it will be a total mess if there are many such
clauses. It means that the actions taken in one case depend on the code
written in a different case - making the code confusing, and losing all
track of code flow. And as well as being extremely difficult for the
programmer to comprehend, it will hinder the compiler's abilities to
generate good object code.
I would need to see a /very/ convincing real-life example before this
would make sense to me.
>
> Bear in mind that in the GUI editor, these expressions would be
> reduced down to visual forms which look like this until expanded:
>
> if (x == 2 <|iftrue|> <|iffalse|>)
> {
> // Code goes here
> }
>
> switch (x)
> {
> case 2 <|iftrue|> <|iffalse|>:
> // Code goes here
> break;
> }
>
> And only when some GUI interaction takes place would they be expanded.
> It makes them easy to see, easy to manage. They can be grabbed hold
> of with the mouse as a single unit and dragged around, etc.
>
Judging from your screenshots, all I see is that these casks will have
syntax highlighting to make them a little more obvious. That does not
change how unnecessary and confusing they are.
> -----
> CAlive also introduces the "always_before" and "always_after" code blocks
> for various things:
>
> // Note: the [once] syntax below indicates "once" is a keyword that
> // is optional, same for [per_call].
> while (some_condition)
> {
> // Code goes here
>
> } always_before [once] [per_call] {
> // Code executes before the while loop begins
> // If once is applied, then it only executes the first time
> // the while loop is traversed throughout the lifetime of
> // the program. If per_call is applied, then it will use
> // a local flag to determine if it should be called.
>
> } always_after [once] [per_call] {
> // Code executes after the while loop exits
> // If once is applied, then it only executes the first time
> // the while loop is traversed throughout the lifetime of
> // the program. If per_call is applied, then it will use
> // a local flag to determine if it should be called.
> }
Why not just write the code before the while loop, after it, or inside
it as appropriate?
Your ideas read like a recipe for meringues:
1. Put 4 egg whites in a bowl.
2. Add 100g of sugar.
3. Beat the eggs before adding the sugar.
4. Bake the meringues for 1.5 hours.
5. The sugar should have been added a spoonful at a time.
I cannot fathom why you think this is a good idea.
>
> -----
> CAlive also introduces the "unless" clause:
>
> do {
> // Code goes here
>
> } unless (some_test1) {
> // Code here will execute upon entry into the block if some_test1
> // fails. It can issue a break; or a retry; after setting up the
> // runtime environment to try again
>
> break;
>
> } unless (some_test2) {
> // More tests can be made
>
> retry [all]; // If all is specified, it retries every test,
> // otherwise, it retries only this test and
> // then continues on to the next (if any).
>
> } while (some_condition);
> // And similarly, always_before and always_after blocks can be added.
>
> In all of the above cases, the code that is inserted in this way so that
> it's encapsulated in the place it's used, helping to create self-
> documenting code. Things that relate to each other relate to each other
> spatially, and not just conceptually. They also convey more of the
> meaning inherent in code.
>
The only meaning it conveys, as far as I can see here, is that the
author of the code can't think in a straight line but leaps back and
forth - and expects the compiler, the computer, and anyone reading the
code to follow the same leaps.
Again, it's going to take a /serious/ example to show any point here.
And then you have to convince us that it is better than normal C or C++,
possibly using exceptions or goto.
> -----
> CAlive also allows do loops to have their test clause at the top:
>
> do while {
> // Code goes here
>
> // } unless (test) { blocks can go here
>
> }; // semicolon here is optional, and ignored
>
>
In C, you have:
while (x) {...};
and
do {...} while (x);
Put the condition where it makes sense.
[toc] | [prev] | [next] | [standalone]
| From | "Rick C. Hodgin" <rick.c.hodgin@gmail.com> |
|---|---|
| Date | 2015-10-30 06:18 -0700 |
| Message-ID | <0bebff8e-3b53-4a4b-8453-199a8cd0aa9d@googlegroups.com> |
| In reply to | #74275 |
On Friday, October 30, 2015 at 8:04:31 AM UTC-4, David Brown wrote:
> On 30/10/15 12:24, Rick C. Hodgin wrote:
> > On Friday, October 30, 2015 at 3:34:25 AM UTC-4, Ian Collins wrote:
> >> Rick C. Hodgin wrote:
> >>> On Thursday, October 29, 2015 at 9:25:39 PM UTC-4, Ian Collins wrote:
> >>>> Rick C. Hodgin wrote:
> >>>>> On Thursday, October 29, 2015 at 5:48:26 PM UTC-4, Bart wrote:
> >>>>>> Does ~|....|~ denote a bit of code that is not immediately evaluated
> >>>>>> (maybe like QUOTE in Lisp)?
> >>>>>
> >>>>> The ~|utility|~ cask is an arbitrary injection of any code. It will
> >>>>> be inserted at whatever point you insert the cask in a statement.
> >>>>> The contents of the utility can contain anything. If it is a larger
> >>>>> block it will be filled with multi-line content between the ~| and |~
> >>>>> sides. However, CAlive provides for another feature whenever larger
> >>>>> bits of code are required. They would typically be used, along with
> >>>>> the (|reference|) casks, instead of the ~|utility|~ cask:
> >>>>
> >>>> If I remember correctly, the last time this topic came up it was
> >>>> demonstrated that C++ cam already do what you were after.
> >>>
> >>> And as I told you back then, and you refused to listen to it, C++
> >>> cannot do what casks do. Nor a dozen other things I propose in
> >>> my language.
> >>
> >> So provide an example use that C++ can't match. If you are attempting
> >> to prove the utility of a new idea, you have to show that is is new.
> >
> > You will see in time. My goals in these posts are to "warm up the
> > audience" by introducing little bits to chew on over time.
>
>
> I can see that point, but I think if you don't come up with something
> interesting soon your audience will wander away and not bother paying
> attention later.
That's fine with me. The people who will remain are the people who
will remain. It's similar to the discussion over in comp.arch, that
those who come to Jesus do so because they have a calling on the
inside.
Those who will use CAlive will see the value I see in the offering,
and come to it for similar reasons.
> I keep hoping you'll come up with something new and
> interesting, or some example in which the casks give code that is
> clearer, simpler, easier to maintain, or in some other way better than
> could be done with existing solutions (C, C++, or extensions in existing
> compilers such as gcc, clang or lcc). So far I have been disappointed -
> but I haven't yet wandered away.
>
> (Note that although your casks and adhocs can - as far as I have seen -
> be replaced by standard C or C++, I strongly disapprove of writing code
> in that style. The implementations using lambdas or macros are merely
> to show that you don't need to invent casks in order to write bad code.)
>
> >
> > -----
> > In addition to the (|reference|) and ~|utility|~ casks, I also introduce
> > the logic cask.
> >
> > I define two basic types:
> >
> > <|meta|> called when the result is true
> > <|mefa|> called when the result is false
> >
> > As an example of a <|logic|> cask:
> >
> > adhoc iftrue { printf("true\n"); }
> > adhoc iffalse { printf("false\n"); }
> >
>
> Normal functions, macros, nested functions and lambdas are all
> alternative ways to define these "adhoc" functions, though in this
> example it is hard to see why you want them to be within the function
> rather than file-level statics, but not simply written directly at the
> place they are called.
>
> Still, macros are the nearest plain C alternative:
>
> #define iftrue printf("true\n")
> #define iffalse printf("false\n")
>
> > if (x == 2 <||meta|iftrue|> <||mefa|iffalse|>)
> > {
> > // Code goes here
> > }
>
> if (x == 2) {
> iftrue;
> // Code goes here
> } else {
> iffalse;
> }
>
> Clear, simple, and obvious. Your casks add nothing.
adhoc touched
|params char* p
{
printf("Touched %s\n", p);
}
if ( x == 2 (|touched|"x"||) <||meta|iftrue|x||> <||mefa|iffalse|x||>
|| y == 1 (|touched|"y"||)
|| z == 3 (|touched|"z"||) <||meta|iftrue|z||> <||mefa|iffalse|z||>)
{
// Code goes here
} else {
// Code goes here
}
In each test, because the casks are inserted after the test, the
execution of the (|touched|) cask indicates it made it that far
through the || expression, and the result of each logic state
will have triggered the appropriate iftrue() and iffalse() calls.
And casks can be inserted anywhere employing similar abilities.
> > switch (x)
> > {
> > case 2 <||meta|iftrue|> <||mefa|iffalse|>:
> > // Code goes here
> > break;
> > }
>
> The "iftrue" part can go directly in the case, just before "Code goes
> here". Again, the standard C is clearer and simpler than the casks.
>
> The "iffalse" part is harder - it is far from clear how it should
> interact with other code. Should it be run for all cases other than 2?
It would be fired in all cases top-down in the case statements until
one which matches is found.
CAlive also allows for non-const values in switch statements, as well
as ranges of values (which I believe are also GCC extensions).
> Should it be run before or after "iftrue" parts for other cases?
> Should that depend on whether those cases are before or after case 2?
>
> Even if you have a single answer to that question, it is not going to be
> obvious when used - and it will be a total mess if there are many such
> clauses. It means that the actions taken in one case depend on the code
> written in a different case - making the code confusing, and losing all
> track of code flow. And as well as being extremely difficult for the
> programmer to comprehend, it will hinder the compiler's abilities to
> generate good object code.
>
> I would need to see a /very/ convincing real-life example before this
> would make sense to me.
There will be one at some point. CAlive is still a ways away from
me bringing it into a tool you can download and test. I'm doing all
of this development in my after-work hours, on weekends, and on
holidays.
> > Bear in mind that in the GUI editor, these expressions would be
> > reduced down to visual forms which look like this until expanded:
> >
> > if (x == 2 <|iftrue|> <|iffalse|>)
> > {
> > // Code goes here
> > }
> >
> > switch (x)
> > {
> > case 2 <|iftrue|> <|iffalse|>:
> > // Code goes here
> > break;
> > }
> >
> > And only when some GUI interaction takes place would they be expanded.
> > It makes them easy to see, easy to manage. They can be grabbed hold
> > of with the mouse as a single unit and dragged around, etc.
>
> Judging from your screenshots, all I see is that these casks will have
> syntax highlighting to make them a little more obvious. That does not
> change how unnecessary and confusing they are.
I have offline drawings I've made over time as I've created little
examples to introduce things.
Casks can also have what I call pips:
(|o|name|o|)
And they can have more than one pip:
(|ooo|name|oo|)
And pips can be opened or closed:
(|Ooo|name|OO")
// "O" means "open", and "o" means closed
// Why "open" and "closed"? Read on...
The original purpose I came up with back in the mid-1990s was to employ
pips to indicate things by context. The open and closed nature
determined how the cask was rendered graphically. If open, the return
parameters, for example, would be shown like this:
// It's actual form: (|O||return|name|)
// How it's rendered on-screen:
+--------+
| return |
|+-------+
||
(|O|name|)
It has a popup which extends up out of the side. When it is closed,
it would be rendered like this:
(o||name|)
The double-|| on the left side indicates it has content there, and the
closed "o" would be used to access it. Similarly, the content on the
right-side would go down:
// It's actual form: (|name|a,b,c||O|)
// How it's rendered on-screen:
(|name|O|)
||
|+------+
| a,b,c |
+-------+
In addition, utility casks operate the same way. And I use the tag
".meta(name)" to give them a display name, as in:
~|lots of code goes here|~.name(fixup)
Then it's rendered on-screen as this when closed, allowing it to be
dragged around and dropped where needed:
~|o|fixup|~
Which allows it to be like this when opened:
+---------------+
| abc = NULL; |
| other_code(); |
| more_code(); |
|+--------------+
||
~|O|fixup|~
The GUI editor handles the re-display, while the hard-and-fast syntax
form exists in text form. But, since computers are our tools and
helpers, there's no reason why the two should not be explicitly tied
together in this supercomputer-on-a-graphics-card era.
> > -----
> > CAlive also introduces the "always_before" and "always_after" code blocks
> > for various things:
> >
> > // Note: the [once] syntax below indicates "once" is a keyword that
> > // is optional, same for [per_call].
> > while (some_condition)
> > {
> > // Code goes here
> >
> > } always_before [once] [per_call] {
> > // Code executes before the while loop begins
> > // If once is applied, then it only executes the first time
> > // the while loop is traversed throughout the lifetime of
> > // the program. If per_call is applied, then it will use
> > // a local flag to determine if it should be called.
> >
> > } always_after [once] [per_call] {
> > // Code executes after the while loop exits
> > // If once is applied, then it only executes the first time
> > // the while loop is traversed throughout the lifetime of
> > // the program. If per_call is applied, then it will use
> > // a local flag to determine if it should be called.
> > }
>
> Why not just write the code before the while loop, after it, or inside
> it as appropriate?
Encapsulation.
> Your ideas read like a recipe for meringues:
>
> 1. Put 4 egg whites in a bowl.
> 2. Add 100g of sugar.
> 3. Beat the eggs before adding the sugar.
> 4. Bake the meringues for 1.5 hours.
> 5. The sugar should have been added a spoonful at a time.
>
> I cannot fathom why you think this is a good idea.
>
> >
> > -----
> > CAlive also introduces the "unless" clause:
> >
> > do {
> > // Code goes here
> >
> > } unless (some_test1) {
> > // Code here will execute upon entry into the block if some_test1
> > // fails. It can issue a break; or a retry; after setting up the
> > // runtime environment to try again
> >
> > break;
> >
> > } unless (some_test2) {
> > // More tests can be made
> >
> > retry [all]; // If all is specified, it retries every test,
> > // otherwise, it retries only this test and
> > // then continues on to the next (if any).
> >
> > } while (some_condition);
> > // And similarly, always_before and always_after blocks can be added.
> >
> > In all of the above cases, the code that is inserted in this way so that
> > it's encapsulated in the place it's used, helping to create self-
> > documenting code. Things that relate to each other relate to each other
> > spatially, and not just conceptually. They also convey more of the
> > meaning inherent in code.
> >
>
> The only meaning it conveys, as far as I can see here, is that the
> author of the code can't think in a straight line but leaps back and
> forth - and expects the compiler, the computer, and anyone reading the
> code to follow the same leaps.
It's all about removing as much as is required from the author having
to figure things out all of hte time. That requirement will still be
there, but by visually putting the code related to the unless clauses
inside the loop, it's immediately obvious to even non-programmers
what it means.
BTW, I've used my wife and son as guinea pigs for some of this, so I
do have corroborating evidence to which I speak. :-)
> Again, it's going to take a /serious/ example to show any point here.
>
> And then you have to convince us that it is better than normal C or C++,
> possibly using exceptions or goto.
>
>
> > -----
> > CAlive also allows do loops to have their test clause at the top:
> >
> > do while {
> > // Code goes here
> >
> > // } unless (test) { blocks can go here
> >
> > }; // semicolon here is optional, and ignored
> >
> >
>
> In C, you have:
>
> while (x) {...};
>
> and
>
> do {...} while (x);
>
> Put the condition where it makes sense.
That's why I allow "do while" and "do { } while" ... they're both do
loops, and it makes more sense to keep them the same than to just use
"while" in one case, and "do" in another.
There are also some x-extensions I'll get into at a later point. I'm
sure you'll love those. :-)
Here's some previews in VXB++ syntax (XBASE-like) in case you can't wait:
http://www.visual-freepro.org/wiki/index.php/Flow_Control#FORX..ENDFORX
http://www.visual-freepro.org/wiki/index.php/Flow_Control#XIF..XELSEIF.2C_XFALLTHROUGH.2C_XGOTO.2C_XEXIT.2C_and_XRETRY
http://www.visual-freepro.org/wiki/index.php/Flow_Control#XELSE.2C_XOVERRIDE_and_XCANCEL
-----
I also introduce a line if statement:
lif (something) code1; code2; code3;
lelse code4; code5; code6;
It differs from the standard syntax:
if (something { code1; code2; code3; }
else { code4; code5; code6; }
...and for exactly the reasons you'd expect, lif and lelse are
fundamental things and they should be easier to read and understand.
-----
I also introduce a full-if statement which tests every condition
all the way through:
fif (x == 4 && y == 3)
{
// Both values were tested, and their results are in implicit
// structure of boolean variables called _fif.l1, _fif.l2, and
// so on.
}
The affixed names can also be changed with override definition casks
(shown here with extra spaces to break it out):
fif ( [|xtest|] x == 4 && [|ytest|] y == 3)
{
// The results are available through _fif.xtest, and _fif.ytest
// as well as _fif.l1 and _fif.l2, as they are created as a
// union.
}
And there's more. But in all honesty, I don't want to spend the day
defending myself. I'm 20+ years in considering these ideas, and I've
really spent the bulk of the last few years considering the finer
details and points as I've become a better C/C++ developer. They are
the things I want to see in a language, and I'm intent on adding them.
Best regards,
Rick C. Hodgin
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2015-10-30 16:23 +0100 |
| Message-ID | <n101t9$u5g$1@dont-email.me> |
| In reply to | #74288 |
On 30/10/15 14:18, Rick C. Hodgin wrote:
> On Friday, October 30, 2015 at 8:04:31 AM UTC-4, David Brown wrote:
>> On 30/10/15 12:24, Rick C. Hodgin wrote:
>>> On Friday, October 30, 2015 at 3:34:25 AM UTC-4, Ian Collins wrote:
>>>> Rick C. Hodgin wrote:
>>>>> On Thursday, October 29, 2015 at 9:25:39 PM UTC-4, Ian Collins wrote:
>>>>>> Rick C. Hodgin wrote:
>>>>>>> On Thursday, October 29, 2015 at 5:48:26 PM UTC-4, Bart wrote:
>>>>>>>> Does ~|....|~ denote a bit of code that is not immediately evaluated
>>>>>>>> (maybe like QUOTE in Lisp)?
>>>>>>>
>>>>>>> The ~|utility|~ cask is an arbitrary injection of any code. It will
>>>>>>> be inserted at whatever point you insert the cask in a statement.
>>>>>>> The contents of the utility can contain anything. If it is a larger
>>>>>>> block it will be filled with multi-line content between the ~| and |~
>>>>>>> sides. However, CAlive provides for another feature whenever larger
>>>>>>> bits of code are required. They would typically be used, along with
>>>>>>> the (|reference|) casks, instead of the ~|utility|~ cask:
>>>>>>
>>>>>> If I remember correctly, the last time this topic came up it was
>>>>>> demonstrated that C++ cam already do what you were after.
>>>>>
>>>>> And as I told you back then, and you refused to listen to it, C++
>>>>> cannot do what casks do. Nor a dozen other things I propose in
>>>>> my language.
>>>>
>>>> So provide an example use that C++ can't match. If you are attempting
>>>> to prove the utility of a new idea, you have to show that is is new.
>>>
>>> You will see in time. My goals in these posts are to "warm up the
>>> audience" by introducing little bits to chew on over time.
>>
>>
>> I can see that point, but I think if you don't come up with something
>> interesting soon your audience will wander away and not bother paying
>> attention later.
>
> That's fine with me. The people who will remain are the people who
> will remain. It's similar to the discussion over in comp.arch, that
> those who come to Jesus do so because they have a calling on the
> inside.
>
> Those who will use CAlive will see the value I see in the offering,
> and come to it for similar reasons.
There is no sign of anyone being interested in CAlive, but several
people are still interested in figuring out what you mean by casks, and
why you would want them. New ideas can be interesting even though
CAlive itself is irrelevant.
>
> adhoc touched
> |params char* p
> {
> printf("Touched %s\n", p);
> }
>
> if ( x == 2 (|touched|"x"||) <||meta|iftrue|x||> <||mefa|iffalse|x||>
> || y == 1 (|touched|"y"||)
> || z == 3 (|touched|"z"||) <||meta|iftrue|z||> <||mefa|iffalse|z||>)
> {
> // Code goes here
>
> } else {
> // Code goes here
> }
bool doCode = false;
if (x == 2) {
touched("x");
iftrue("x");
doCode = true;
} else {
iffalse("x");
if (y == 1) {
touched("y");
doCode = true;
} else if (z == 3) {
touched("z");
iftrue("z");
doCode = true;
} else {
iffalse("z");
}
}
if (doCode) {
// Code goes here
} else {
// Code goes here
}
It could be arranged in several ways, depending on what you are actually
trying to do - something that is hard to see from such artificial
examples. Some people feel that using "goto" rather than a boolean
doCode is better, others might prefer to use multiple return statements.
There are many options without introducing a new syntax.
(And I thought || now meant "whitespace" ?)
>
> In each test, because the casks are inserted after the test, the
> execution of the (|touched|) cask indicates it made it that far
> through the || expression, and the result of each logic state
> will have triggered the appropriate iftrue() and iffalse() calls.
>
> And casks can be inserted anywhere employing similar abilities.
>
>>> switch (x)
>>> {
>>> case 2 <||meta|iftrue|> <||mefa|iffalse|>:
>>> // Code goes here
>>> break;
>>> }
>>
>> The "iftrue" part can go directly in the case, just before "Code goes
>> here". Again, the standard C is clearer and simpler than the casks.
>>
>> The "iffalse" part is harder - it is far from clear how it should
>> interact with other code. Should it be run for all cases other than 2?
>
> It would be fired in all cases top-down in the case statements until
> one which matches is found.
>
> CAlive also allows for non-const values in switch statements, as well
> as ranges of values (which I believe are also GCC extensions).
Case ranges are a good idea, but I'm a little sceptical about allowing
non-cost values. I think allowing constant values of other types (such
as strings) would be a more useful change. A key point about switches
is that the order does not matter (except for fall-through if you don't
have a "break") - it should not be a sequential series of tests for
efficiency reasons. That is hard to achieve with variable cases, and
impossible if cases depend on each other for ordering.
>
>> Should it be run before or after "iftrue" parts for other cases?
>> Should that depend on whether those cases are before or after case 2?
>>
>> Even if you have a single answer to that question, it is not going to be
>> obvious when used - and it will be a total mess if there are many such
>> clauses. It means that the actions taken in one case depend on the code
>> written in a different case - making the code confusing, and losing all
>> track of code flow. And as well as being extremely difficult for the
>> programmer to comprehend, it will hinder the compiler's abilities to
>> generate good object code.
>>
>> I would need to see a /very/ convincing real-life example before this
>> would make sense to me.
>
> There will be one at some point. CAlive is still a ways away from
> me bringing it into a tool you can download and test. I'm doing all
> of this development in my after-work hours, on weekends, and on
> holidays.
Don't worry about making it possible for others to download or test -
and as I have said before, I don't think it is a good use of your time.
But you certainly need to be able to write real, convincing examples
before it makes sense to try to implement them!
>
>>> Bear in mind that in the GUI editor, these expressions would be
>>> reduced down to visual forms which look like this until expanded:
>>>
>>> if (x == 2 <|iftrue|> <|iffalse|>)
>>> {
>>> // Code goes here
>>> }
>>>
>>> switch (x)
>>> {
>>> case 2 <|iftrue|> <|iffalse|>:
>>> // Code goes here
>>> break;
>>> }
>>>
>>> And only when some GUI interaction takes place would they be expanded.
>>> It makes them easy to see, easy to manage. They can be grabbed hold
>>> of with the mouse as a single unit and dragged around, etc.
>>
>> Judging from your screenshots, all I see is that these casks will have
>> syntax highlighting to make them a little more obvious. That does not
>> change how unnecessary and confusing they are.
>
> I have offline drawings I've made over time as I've created little
> examples to introduce things.
>
> Casks can also have what I call pips:
>
> (|o|name|o|)
>
> And they can have more than one pip:
>
> (|ooo|name|oo|)
>
> And pips can be opened or closed:
>
> (|Ooo|name|OO")
> // "O" means "open", and "o" means closed
> // Why "open" and "closed"? Read on...
>
> The original purpose I came up with back in the mid-1990s was to employ
> pips to indicate things by context. The open and closed nature
> determined how the cask was rendered graphically. If open, the return
> parameters, for example, would be shown like this:
>
> // It's actual form: (|O||return|name|)
>
> // How it's rendered on-screen:
>
> +--------+
> | return |
> |+-------+
> ||
> (|O|name|)
>
> It has a popup which extends up out of the side. When it is closed,
> it would be rendered like this:
>
> (o||name|)
>
> The double-|| on the left side indicates it has content there, and the
> closed "o" would be used to access it. Similarly, the content on the
> right-side would go down:
>
> // It's actual form: (|name|a,b,c||O|)
>
> // How it's rendered on-screen:
>
> (|name|O|)
> ||
> |+------+
> | a,b,c |
> +-------+
>
> In addition, utility casks operate the same way. And I use the tag
> ".meta(name)" to give them a display name, as in:
>
> ~|lots of code goes here|~.name(fixup)
>
> Then it's rendered on-screen as this when closed, allowing it to be
> dragged around and dropped where needed:
>
> ~|o|fixup|~
>
> Which allows it to be like this when opened:
>
> +---------------+
> | abc = NULL; |
> | other_code(); |
> | more_code(); |
> |+--------------+
> ||
> ~|O|fixup|~
>
> The GUI editor handles the re-display, while the hard-and-fast syntax
> form exists in text form. But, since computers are our tools and
> helpers, there's no reason why the two should not be explicitly tied
> together in this supercomputer-on-a-graphics-card era.
>
This is all crazy - I can't think of a better word for it. It's insane.
The sort of things you are putting into your casks are not little bits
of notes or comments. They are essential parts of the code and the
working of the program. You can't just pick parts of the language and
decide that /these/ bits will only be visible when you put your mouse
over them, or that /those/ bits will be hidden by default.
I'm sorry - I've been trying to be diplomatic, and trying to be
supportive and give constructive criticism and useful questions rather
than ridicule your ideas, but I have my limits.
>>> -----
>>> CAlive also introduces the "always_before" and "always_after" code blocks
>>> for various things:
>>>
>>> // Note: the [once] syntax below indicates "once" is a keyword that
>>> // is optional, same for [per_call].
>>> while (some_condition)
>>> {
>>> // Code goes here
>>>
>>> } always_before [once] [per_call] {
>>> // Code executes before the while loop begins
>>> // If once is applied, then it only executes the first time
>>> // the while loop is traversed throughout the lifetime of
>>> // the program. If per_call is applied, then it will use
>>> // a local flag to determine if it should be called.
>>>
>>> } always_after [once] [per_call] {
>>> // Code executes after the while loop exits
>>> // If once is applied, then it only executes the first time
>>> // the while loop is traversed throughout the lifetime of
>>> // the program. If per_call is applied, then it will use
>>> // a local flag to determine if it should be called.
>>> }
>>
>> Why not just write the code before the while loop, after it, or inside
>> it as appropriate?
>
> Encapsulation.
Name-dropping a technical term is not an explanation.
>
>> Your ideas read like a recipe for meringues:
>>
>> 1. Put 4 egg whites in a bowl.
>> 2. Add 100g of sugar.
>> 3. Beat the eggs before adding the sugar.
>> 4. Bake the meringues for 1.5 hours.
>> 5. The sugar should have been added a spoonful at a time.
>>
>> I cannot fathom why you think this is a good idea.
>>
>>>
>>> -----
>>> CAlive also introduces the "unless" clause:
>>>
>>> do {
>>> // Code goes here
>>>
>>> } unless (some_test1) {
>>> // Code here will execute upon entry into the block if some_test1
>>> // fails. It can issue a break; or a retry; after setting up the
>>> // runtime environment to try again
>>>
>>> break;
>>>
>>> } unless (some_test2) {
>>> // More tests can be made
>>>
>>> retry [all]; // If all is specified, it retries every test,
>>> // otherwise, it retries only this test and
>>> // then continues on to the next (if any).
>>>
>>> } while (some_condition);
>>> // And similarly, always_before and always_after blocks can be added.
>>>
>>> In all of the above cases, the code that is inserted in this way so that
>>> it's encapsulated in the place it's used, helping to create self-
>>> documenting code. Things that relate to each other relate to each other
>>> spatially, and not just conceptually. They also convey more of the
>>> meaning inherent in code.
>>>
>>
>> The only meaning it conveys, as far as I can see here, is that the
>> author of the code can't think in a straight line but leaps back and
>> forth - and expects the compiler, the computer, and anyone reading the
>> code to follow the same leaps.
>
> It's all about removing as much as is required from the author having
> to figure things out all of hte time. That requirement will still be
> there, but by visually putting the code related to the unless clauses
> inside the loop, it's immediately obvious to even non-programmers
> what it means.
>
> BTW, I've used my wife and son as guinea pigs for some of this, so I
> do have corroborating evidence to which I speak. :-)
I do not take that as any sort of corroborating evidence.
>
>> Again, it's going to take a /serious/ example to show any point here.
>>
>> And then you have to convince us that it is better than normal C or C++,
>> possibly using exceptions or goto.
>>
>>
>>> -----
>>> CAlive also allows do loops to have their test clause at the top:
>>>
>>> do while {
>>> // Code goes here
>>>
>>> // } unless (test) { blocks can go here
>>>
>>> }; // semicolon here is optional, and ignored
>>>
>>>
>>
>> In C, you have:
>>
>> while (x) {...};
>>
>> and
>>
>> do {...} while (x);
>>
>> Put the condition where it makes sense.
>
> That's why I allow "do while" and "do { } while" ... they're both do
> loops, and it makes more sense to keep them the same than to just use
> "while" in one case, and "do" in another.
Call it "do while (x) { ... }" if you like, that's just syntactic
detail. The principle is the same.
>
> There are also some x-extensions I'll get into at a later point. I'm
> sure you'll love those. :-)
>
> Here's some previews in VXB++ syntax (XBASE-like) in case you can't wait:
>
> http://www.visual-freepro.org/wiki/index.php/Flow_Control#FORX..ENDFORX
> http://www.visual-freepro.org/wiki/index.php/Flow_Control#XIF..XELSEIF.2C_XFALLTHROUGH.2C_XGOTO.2C_XEXIT.2C_and_XRETRY
> http://www.visual-freepro.org/wiki/index.php/Flow_Control#XELSE.2C_XOVERRIDE_and_XCANCEL
>
> -----
> I also introduce a line if statement:
>
> lif (something) code1; code2; code3;
> lelse code4; code5; code6;
>
> It differs from the standard syntax:
>
> if (something { code1; code2; code3; }
> else { code4; code5; code6; }
>
> ...and for exactly the reasons you'd expect, lif and lelse are
> fundamental things and they should be easier to read and understand.
>
/How/ does "lif" and "lelse" differ from C's "if" and "else" ? If all
you are doing is making the group built-in, then I approve of the idea -
the optional brackets in C's "if" statements is a source of many errors.
But rather than inventing new keywords, just change those of C. Either
make brackets required, so that "if (x) " /must/ be followed by {, or
make the if statement end with an "endif" or "fi" statement:
if (x)
code1;
code2;
else
code3;
fi
There is no advantage in having two almost the same keywords for the
same thing.
> -----
> I also introduce a full-if statement which tests every condition
> all the way through:
>
> fif (x == 4 && y == 3)
> {
> // Both values were tested, and their results are in implicit
> // structure of boolean variables called _fif.l1, _fif.l2, and
> // so on.
> }
>
That's a terrible idea. It means that the interpretation of the
expression inside the brackets depends on its context. You should
strive to make your language as consistent as possible, not invent new
ways to make it inconsistent.
And don't invent implicit structures like that. Let people write "(x ==
4)" inside the code body and make your compiler figure out if it is most
efficient to re-do the check, or to store the results of the previous check.
> The affixed names can also be changed with override definition casks
> (shown here with extra spaces to break it out):
>
> fif ( [|xtest|] x == 4 && [|ytest|] y == 3)
> {
> // The results are available through _fif.xtest, and _fif.ytest
> // as well as _fif.l1 and _fif.l2, as they are created as a
> // union.
> }
bool xtest, ytest;
if ((xtest = (x == 4)) && (ytest = (y == 3))) ...
or
bool xtest = (x == 4);
bool ytest = (y == 3);
if (xtest && ytest) ....
It is going to be incredibly rare that anyone would need to make use of
such structures. Rather than inventing ever more complex structures,
keywords, and features that will almost never be used, let the user
write that extra line or two when needed.
>
> And there's more. But in all honesty, I don't want to spend the day
> defending myself. I'm 20+ years in considering these ideas, and I've
> really spent the bulk of the last few years considering the finer
> details and points as I've become a better C/C++ developer. They are
> the things I want to see in a language, and I'm intent on adding them.
>
It is entirely clear that you will go your own way, as usual. (It is
rare for anyone to change their minds as a result of a thread on
Usenet.) But I assume you are making these posts in the hope of getting
some feedback, so I give it as honestly and clearly as I can.
[toc] | [prev] | [next] | [standalone]
| From | "Rick C. Hodgin" <rick.c.hodgin@gmail.com> |
|---|---|
| Date | 2015-10-30 09:25 -0700 |
| Message-ID | <a3736fbd-9ac9-479a-a99d-3541284744f6@googlegroups.com> |
| In reply to | #74315 |
On Friday, October 30, 2015 at 11:23:35 AM UTC-4, David Brown wrote:
> On 30/10/15 14:18, Rick C. Hodgin wrote:
> > On Friday, October 30, 2015 at 8:04:31 AM UTC-4, David Brown wrote:
> >> On 30/10/15 12:24, Rick C. Hodgin wrote:
> >>> On Friday, October 30, 2015 at 3:34:25 AM UTC-4, Ian Collins wrote:
> >>>> Rick C. Hodgin wrote:
> >>>>> On Thursday, October 29, 2015 at 9:25:39 PM UTC-4, Ian Collins wrote:
> >>>>>> Rick C. Hodgin wrote:
> >>>>>>> On Thursday, October 29, 2015 at 5:48:26 PM UTC-4, Bart wrote:
> >>>>>>>> Does ~|....|~ denote a bit of code that is not immediately evaluated
> >>>>>>>> (maybe like QUOTE in Lisp)?
> >>>>>>>
> >>>>>>> The ~|utility|~ cask is an arbitrary injection of any code. It will
> >>>>>>> be inserted at whatever point you insert the cask in a statement.
> >>>>>>> The contents of the utility can contain anything. If it is a larger
> >>>>>>> block it will be filled with multi-line content between the ~| and |~
> >>>>>>> sides. However, CAlive provides for another feature whenever larger
> >>>>>>> bits of code are required. They would typically be used, along with
> >>>>>>> the (|reference|) casks, instead of the ~|utility|~ cask:
> >>>>>>
> >>>>>> If I remember correctly, the last time this topic came up it was
> >>>>>> demonstrated that C++ cam already do what you were after.
> >>>>>
> >>>>> And as I told you back then, and you refused to listen to it, C++
> >>>>> cannot do what casks do. Nor a dozen other things I propose in
> >>>>> my language.
> >>>>
> >>>> So provide an example use that C++ can't match. If you are attempting
> >>>> to prove the utility of a new idea, you have to show that is is new.
> >>>
> >>> You will see in time. My goals in these posts are to "warm up the
> >>> audience" by introducing little bits to chew on over time.
> >>
> >>
> >> I can see that point, but I think if you don't come up with something
> >> interesting soon your audience will wander away and not bother paying
> >> attention later.
> >
> > That's fine with me. The people who will remain are the people who
> > will remain. It's similar to the discussion over in comp.arch, that
> > those who come to Jesus do so because they have a calling on the
> > inside.
> >
> > Those who will use CAlive will see the value I see in the offering,
> > and come to it for similar reasons.
>
> There is no sign of anyone being interested in CAlive, but several
> people are still interested in figuring out what you mean by casks, and
> why you would want them. New ideas can be interesting even though
> CAlive itself is irrelevant.
>
> >
> > adhoc touched
> > |params char* p
> > {
> > printf("Touched %s\n", p);
> > }
> >
> > if ( x == 2 (|touched|"x"||) <||meta|iftrue|x||> <||mefa|iffalse|x||>
> > || y == 1 (|touched|"y"||)
> > || z == 3 (|touched|"z"||) <||meta|iftrue|z||> <||mefa|iffalse|z||>)
> > {
> > // Code goes here
> >
> > } else {
> > // Code goes here
> > }
>
>
> bool doCode = false;
> if (x == 2) {
> touched("x");
> iftrue("x");
> doCode = true;
> } else {
> iffalse("x");
> if (y == 1) {
> touched("y");
> doCode = true;
> } else if (z == 3) {
> touched("z");
> iftrue("z");
> doCode = true;
> } else {
> iffalse("z");
> }
> }
> if (doCode) {
> // Code goes here
> } else {
> // Code goes here
> }
Yup. A person could code that way if s/he wanted to.
> It could be arranged in several ways, depending on what you are actually
> trying to do - something that is hard to see from such artificial
> examples. Some people feel that using "goto" rather than a boolean
> doCode is better, others might prefer to use multiple return statements.
> There are many options without introducing a new syntax.
>
> (And I thought || now meant "whitespace" ?)
Only when it's the first non-whitespace character on a line, and not
part of another thing, such as an if, lif, fif, etc.
> > In each test, because the casks are inserted after the test, the
> > execution of the (|touched|) cask indicates it made it that far
> > through the || expression, and the result of each logic state
> > will have triggered the appropriate iftrue() and iffalse() calls.
> >
> > And casks can be inserted anywhere employing similar abilities.
> >
> >>> switch (x)
> >>> {
> >>> case 2 <||meta|iftrue|> <||mefa|iffalse|>:
> >>> // Code goes here
> >>> break;
> >>> }
> >>
> >> The "iftrue" part can go directly in the case, just before "Code goes
> >> here". Again, the standard C is clearer and simpler than the casks.
> >>
> >> The "iffalse" part is harder - it is far from clear how it should
> >> interact with other code. Should it be run for all cases other than 2?
> >
> > It would be fired in all cases top-down in the case statements until
> > one which matches is found.
> >
> > CAlive also allows for non-const values in switch statements, as well
> > as ranges of values (which I believe are also GCC extensions).
>
> Case ranges are a good idea, but I'm a little sceptical about allowing
> non-cost values. I think allowing constant values of other types (such
> as strings) would be a more useful change. A key point about switches
> is that the order does not matter (except for fall-through if you don't
> have a "break")
Of course the order matters. And in CAlive, it will matter directly
because you can inject casks at any point.
WYSIWYG in source code, through to output code, short of optimizations
which are visible in CAlive, as it shows every change made throughout
the optimization process.
But, the initial versions of CAlive will not support anything more
than the simplest optimizations.
> - it should not be a sequential series of tests for
> efficiency reasons. That is hard to achieve with variable cases, and
> impossible if cases depend on each other for ordering.
Non-constant values basically turn it into a more structured way of
creating if..else if..else if... statements. No need for { }
sequences, and the added ability to directly fall through.
> >> Should it be run before or after "iftrue" parts for other cases?
> >> Should that depend on whether those cases are before or after case 2?
> >>
> >> Even if you have a single answer to that question, it is not going to be
> >> obvious when used - and it will be a total mess if there are many such
> >> clauses. It means that the actions taken in one case depend on the code
> >> written in a different case - making the code confusing, and losing all
> >> track of code flow. And as well as being extremely difficult for the
> >> programmer to comprehend, it will hinder the compiler's abilities to
> >> generate good object code.
> >>
> >> I would need to see a /very/ convincing real-life example before this
> >> would make sense to me.
> >
> > There will be one at some point. CAlive is still a ways away from
> > me bringing it into a tool you can download and test. I'm doing all
> > of this development in my after-work hours, on weekends, and on
> > holidays.
>
> Don't worry about making it possible for others to download or test -
> and as I have said before, I don't think it is a good use of your time.
Well as you know it goes like this: When it's ready for me to use in
any kind of non-development state, it will then be ready for others to
use. So the two go hand-in-hand.
> But you certainly need to be able to write real, convincing examples
> before it makes sense to try to implement them!
Being as this is a new language, I have tried to demonstrate the
functionality of the operations. I think what I have shown makes
it clear. When I am able to actually introduce these abilities
into code, as through the compiler facilities of CAlive actually
being developed and working, such an example will be forthcoming.
I view the cask as a fundamental building block of all future
source code. I view the blocks of code that will be created more
like what I have in mind for my Logician software, which uses a
graphical node editor to allows things to be plugged up graphically,
and to be manipulate as objects in 3D space creating logical
structures rather than flat code bases. I want people to write
code more like they think... and that's where CAlive is ultimately
heading to.
CAlive will also be the fundamental compiler for use with Logician.
> >>> Bear in mind that in the GUI editor, these expressions would be
> >>> reduced down to visual forms which look like this until expanded:
> >>>
> >>> if (x == 2 <|iftrue|> <|iffalse|>)
> >>> {
> >>> // Code goes here
> >>> }
> >>>
> >>> switch (x)
> >>> {
> >>> case 2 <|iftrue|> <|iffalse|>:
> >>> // Code goes here
> >>> break;
> >>> }
> >>>
> >>> And only when some GUI interaction takes place would they be expanded.
> >>> It makes them easy to see, easy to manage. They can be grabbed hold
> >>> of with the mouse as a single unit and dragged around, etc.
> >>
> >> Judging from your screenshots, all I see is that these casks will have
> >> syntax highlighting to make them a little more obvious. That does not
> >> change how unnecessary and confusing they are.
> >
> > I have offline drawings I've made over time as I've created little
> > examples to introduce things.
> >
> > Casks can also have what I call pips:
> >
> > (|o|name|o|)
> >
> > And they can have more than one pip:
> >
> > (|ooo|name|oo|)
> >
> > And pips can be opened or closed:
> >
> > (|Ooo|name|OO")
> > // "O" means "open", and "o" means closed
> > // Why "open" and "closed"? Read on...
> >
> > The original purpose I came up with back in the mid-1990s was to employ
> > pips to indicate things by context. The open and closed nature
> > determined how the cask was rendered graphically. If open, the return
> > parameters, for example, would be shown like this:
> >
> > // It's actual form: (|O||return|name|)
> >
> > // How it's rendered on-screen:
> >
> > +--------+
> > | return |
> > |+-------+
> > ||
> > (|O|name|)
> >
> > It has a popup which extends up out of the side. When it is closed,
> > it would be rendered like this:
> >
> > (o||name|)
> >
> > The double-|| on the left side indicates it has content there, and the
> > closed "o" would be used to access it. Similarly, the content on the
> > right-side would go down:
> >
> > // It's actual form: (|name|a,b,c||O|)
> >
> > // How it's rendered on-screen:
> >
> > (|name|O|)
> > ||
> > |+------+
> > | a,b,c |
> > +-------+
> >
> > In addition, utility casks operate the same way. And I use the tag
> > ".meta(name)" to give them a display name, as in:
> >
> > ~|lots of code goes here|~.name(fixup)
> >
> > Then it's rendered on-screen as this when closed, allowing it to be
> > dragged around and dropped where needed:
> >
> > ~|o|fixup|~
> >
> > Which allows it to be like this when opened:
> >
> > +---------------+
> > | abc = NULL; |
> > | other_code(); |
> > | more_code(); |
> > |+--------------+
> > ||
> > ~|O|fixup|~
> >
> > The GUI editor handles the re-display, while the hard-and-fast syntax
> > form exists in text form. But, since computers are our tools and
> > helpers, there's no reason why the two should not be explicitly tied
> > together in this supercomputer-on-a-graphics-card era.
> >
>
> This is all crazy - I can't think of a better word for it. It's insane.
You have my permission to no longer reply to my posts if you want. I
know it would make my life a little nicer.
> The sort of things you are putting into your casks are not little bits
> of notes or comments. They are essential parts of the code and the
> working of the program. You can't just pick parts of the language and
> decide that /these/ bits will only be visible when you put your mouse
> over them, or that /those/ bits will be hidden by default.
>
> I'm sorry - I've been trying to be diplomatic, and trying to be
> supportive and give constructive criticism and useful questions rather
> than ridicule your ideas, but I have my limits.
Then please accept my invitation to bow out from all future discourse
regarding CAlive. I'm sure we'll both be better off for it.
> >>> -----
> >>> CAlive also introduces the "always_before" and "always_after" code blocks
> >>> for various things:
> >>>
> >>> // Note: the [once] syntax below indicates "once" is a keyword that
> >>> // is optional, same for [per_call].
> >>> while (some_condition)
> >>> {
> >>> // Code goes here
> >>>
> >>> } always_before [once] [per_call] {
> >>> // Code executes before the while loop begins
> >>> // If once is applied, then it only executes the first time
> >>> // the while loop is traversed throughout the lifetime of
> >>> // the program. If per_call is applied, then it will use
> >>> // a local flag to determine if it should be called.
> >>>
> >>> } always_after [once] [per_call] {
> >>> // Code executes after the while loop exits
> >>> // If once is applied, then it only executes the first time
> >>> // the while loop is traversed throughout the lifetime of
> >>> // the program. If per_call is applied, then it will use
> >>> // a local flag to determine if it should be called.
> >>> }
> >>
> >> Why not just write the code before the while loop, after it, or inside
> >> it as appropriate?
> >
> > Encapsulation.
>
> Name-dropping a technical term is not an explanation.
It is the reason why they exist. They are directly related to the
loops... so they are included within it.
Code outside of a loop can be related to the loop, or it can be related
to something else. By putting it inside the loop, that variable is
resolved, and turned into a constant... Simplify. Reduce.
> >> Your ideas read like a recipe for meringues:
> >>
> >> 1. Put 4 egg whites in a bowl.
> >> 2. Add 100g of sugar.
> >> 3. Beat the eggs before adding the sugar.
> >> 4. Bake the meringues for 1.5 hours.
> >> 5. The sugar should have been added a spoonful at a time.
> >>
> >> I cannot fathom why you think this is a good idea.
> >>
> >>>
> >>> -----
> >>> CAlive also introduces the "unless" clause:
> >>>
> >>> do {
> >>> // Code goes here
> >>>
> >>> } unless (some_test1) {
> >>> // Code here will execute upon entry into the block if some_test1
> >>> // fails. It can issue a break; or a retry; after setting up the
> >>> // runtime environment to try again
> >>>
> >>> break;
> >>>
> >>> } unless (some_test2) {
> >>> // More tests can be made
> >>>
> >>> retry [all]; // If all is specified, it retries every test,
> >>> // otherwise, it retries only this test and
> >>> // then continues on to the next (if any).
> >>>
> >>> } while (some_condition);
> >>> // And similarly, always_before and always_after blocks can be added.
> >>>
> >>> In all of the above cases, the code that is inserted in this way so that
> >>> it's encapsulated in the place it's used, helping to create self-
> >>> documenting code. Things that relate to each other relate to each other
> >>> spatially, and not just conceptually. They also convey more of the
> >>> meaning inherent in code.
> >>>
> >>
> >> The only meaning it conveys, as far as I can see here, is that the
> >> author of the code can't think in a straight line but leaps back and
> >> forth - and expects the compiler, the computer, and anyone reading the
> >> code to follow the same leaps.
> >
> > It's all about removing as much as is required from the author having
> > to figure things out all of hte time. That requirement will still be
> > there, but by visually putting the code related to the unless clauses
> > inside the loop, it's immediately obvious to even non-programmers
> > what it means.
> >
> > BTW, I've used my wife and son as guinea pigs for some of this, so I
> > do have corroborating evidence to which I speak. :-)
>
> I do not take that as any sort of corroborating evidence.
Neither of them are programmers. And both of them are truly in all
ways not programmers. So, when I describe something to them, they
approach me with an honest desire to help me, and when I explain
something they give me criticism designed to help me. And they are
very good at it. Especially my wife.
> >> Again, it's going to take a /serious/ example to show any point here.
> >>
> >> And then you have to convince us that it is better than normal C or C++,
> >> possibly using exceptions or goto.
> >>
> >>
> >>> -----
> >>> CAlive also allows do loops to have their test clause at the top:
> >>>
> >>> do while {
> >>> // Code goes here
> >>>
> >>> // } unless (test) { blocks can go here
> >>>
> >>> }; // semicolon here is optional, and ignored
> >>>
> >>>
> >>
> >> In C, you have:
> >>
> >> while (x) {...};
> >>
> >> and
> >>
> >> do {...} while (x);
> >>
> >> Put the condition where it makes sense.
> >
> > That's why I allow "do while" and "do { } while" ... they're both do
> > loops, and it makes more sense to keep them the same than to just use
> > "while" in one case, and "do" in another.
>
> Call it "do while (x) { ... }" if you like, that's just syntactic
> detail. The principle is the same.
Yes. It's a syntax detail. But it also conveys the meaning that
these are both "do { } while" and "do while { }" loops, both do
loops.
That distinction means something.
> > There are also some x-extensions I'll get into at a later point. I'm
> > sure you'll love those. :-)
> >
> > Here's some previews in VXB++ syntax (XBASE-like) in case you can't wait:
> >
> > http://www.visual-freepro.org/wiki/index.php/Flow_Control#FORX..ENDFORX
> > http://www.visual-freepro.org/wiki/index.php/Flow_Control#XIF..XELSEIF.2C_XFALLTHROUGH.2C_XGOTO.2C_XEXIT.2C_and_XRETRY
> > http://www.visual-freepro.org/wiki/index.php/Flow_Control#XELSE.2C_XOVERRIDE_and_XCANCEL
> >
> > -----
> > I also introduce a line if statement:
> >
> > lif (something) code1; code2; code3;
> > lelse code4; code5; code6;
> >
> > It differs from the standard syntax:
> >
> > if (something { code1; code2; code3; }
> > else { code4; code5; code6; }
> >
> > ...and for exactly the reasons you'd expect, lif and lelse are
> > fundamental things and they should be easier to read and understand.
> >
>
> /How/ does "lif" and "lelse" differ from C's "if" and "else" ? If all
> you are doing is making the group built-in, then I approve of the idea -
> the optional brackets in C's "if" statements is a source of many errors.
> But rather than inventing new keywords, just change those of C. Either
> make brackets required, so that "if (x) " /must/ be followed by {, or
> make the if statement end with an "endif" or "fi" statement:
>
> if (x)
> code1;
> code2;
> else
> code3;
> fi
>
> There is no advantage in having two almost the same keywords for the
> same thing.
I demonstrated the difference in my example above. It is a syntax
difference, and it conveys explicitly the meaning through use of
the lif and lelse keywords.
> > -----
> > I also introduce a full-if statement which tests every condition
> > all the way through:
> >
> > fif (x == 4 && y == 3)
> > {
> > // Both values were tested, and their results are in implicit
> > // structure of boolean variables called _fif.l1, _fif.l2, and
> > // so on.
> > }
> >
>
> That's a terrible idea. It means that the interpretation of the
> expression inside the brackets depends on its context. You should
> strive to make your language as consistent as possible, not invent new
> ways to make it inconsistent.
>
> And don't invent implicit structures like that. Let people write "(x ==
> 4)" inside the code body and make your compiler figure out if it is most
> efficient to re-do the check, or to store the results of the previous check.
I appreciate the advice. I'll take it under advisement.
> > The affixed names can also be changed with override definition casks
> > (shown here with extra spaces to break it out):
> >
> > fif ( [|xtest|] x == 4 && [|ytest|] y == 3)
> > {
> > // The results are available through _fif.xtest, and _fif.ytest
> > // as well as _fif.l1 and _fif.l2, as they are created as a
> > // union.
> > }
>
> bool xtest, ytest;
> if ((xtest = (x == 4)) && (ytest = (y == 3))) ...
>
> or
>
> bool xtest = (x == 4);
> bool ytest = (y == 3);
> if (xtest && ytest) ....
>
> It is going to be incredibly rare that anyone would need to make use of
> such structures. Rather than inventing ever more complex structures,
> keywords, and features that will almost never be used, let the user
> write that extra line or two when needed.
I'll take it under advisement.
> > And there's more. But in all honesty, I don't want to spend the day
> > defending myself. I'm 20+ years in considering these ideas, and I've
> > really spent the bulk of the last few years considering the finer
> > details and points as I've become a better C/C++ developer. They are
> > the things I want to see in a language, and I'm intent on adding them.
>
> It is entirely clear that you will go your own way, as usual.
It's what leaders do.
> (It is rare for anyone to change their minds as a result of a thread on
> Usenet.) But I assume you are making these posts in the hope of getting
> some feedback, so I give it as honestly and clearly as I can.
I have changed my mind on many things, the most recent of which was Bart's
contribution of the .. for auto-resolve. And there was one sometime
before that I can't remember... but it came also from comp.lang.c, and I
think it also came from Bart.
Best regards,
Rick C. Hodgin
[toc] | [prev] | [next] | [standalone]
| From | gazelle@shell.xmission.com (Kenny McCormack) |
|---|---|
| Date | 2015-10-30 16:47 +0000 |
| Message-ID | <n106uv$3io$1@news.xmission.com> |
| In reply to | #74315 |
In article <n101t9$u5g$1@dont-email.me>,
David Brown <david.brown@hesbynett.no> wrote:
...
>It is entirely clear that you will go your own way, as usual. (It is
>rare for anyone to change their minds as a result of a thread on
>Usenet.) But I assume you are making these posts in the hope of getting
>some feedback, so I give it as honestly and clearly as I can.
A few comments:
1) Re: Rick's proposed 'fif' statement (and similar constructs that
involve redefining the meaning of things like "&&" and "||"). I
think it is important to realize that Rick is an amateur language
designer (by his own statements - i.e., that is not a slam - it is
a fact based on his own statements) and his ideas reflect that.
The fact is that a lot of people don't really understand that &&
and || are (in C and most C-like languages) part of the expression
syntax and *not* part of the "if"/"while"/etc syntax. Since they
only see them used in the conditional/iterative statements, these
people assume that they are part of the syntax of those kinds of
statements. Therefore, it is entirely reasonable for them to
assume that their usage can be redefined in terms of the syntax of
those statements.
2) I don't like that many of you are trying to discourage Rick in his
pursuits. For one thing, as I've said elsewhere, this newsgroup
would be pretty boring without him - there's only so many times we
can go on debating how to prototype main() and/or whether or not
you should cast the return value of malloc(). As long as Rick is
willing to entertain us, I'm happy to be entertained.
For another, trying to do something that is impossible can often be
a good learning experience. This is true both at the personal
level and on an historical level. The best historical example of
this is alchemy - many useful and important things were discovered
along the way, even though the stated goal was in vain.
In fact, a similar tangle in going on in another forum that I
participate in. There, some guy is trying to do something that we
(the smart people on the forum) all know is impossible (say, like
"squaring the circle"). But many/most of the other smart people on
that forum are spending all their time telling him:
a) How impossible it is
and
b) That he should cease and desist immediately (and this in no
uncertain terms!)
I, on the other hand, have been telling him to continue (and to
ignore the others) on the theory that he will learn something from
the experience. And that, as they all say, is the important thing
(that's what it's all about!)
3) I actually think it is good to see how language design is done by an
amateur. Charming, like watching amateur sports. In fact, I
think a lot of us are blinded by the fact that we know too much
about implementation. People who understand implementation tend to
design languages that end up looking and behaving like, well, C.
Vis a vis, I think that many of the more esoteric scripting
languages were designed by people who don't understand
implementation. It is interesting to see how computer languages
get designed by artistic people rather than by comp-sci people.
Rick seems to be a good, living example of this.
--
I've been watching cat videos on YouTube. More content and closer to
the truth than anything on Fox.
[toc] | [prev] | [next] | [standalone]
| From | "Rick C. Hodgin" <rick.c.hodgin@gmail.com> |
|---|---|
| Date | 2015-10-30 10:13 -0700 |
| Message-ID | <c08ac2ea-ed63-4b79-8af5-1a4249dce626@googlegroups.com> |
| In reply to | #74342 |
On Friday, October 30, 2015 at 12:47:49 PM UTC-4, Kenny McCormack wrote:
> The fact is that a lot of people don't really understand that &&
> and || are (in C and most C-like languages) part of the expression
> syntax and *not* part of the "if"/"while"/etc syntax. Since they
> only see them used in the conditional/iterative statements, these
> people assume that they are part of the syntax of those kinds of
> statements. Therefore, it is entirely reasonable for them to
> assume that their usage can be redefined in terms of the syntax of
> those statements.
See lines 4301, 4325, 4380, or if the line numbers are different, search
for "*tlLeft || *tlMiddle" or "llIsCAS = ":
https://github.com/RickCHodgin/libsf/blob/master/source/vjr/source/vjr_sup.cpp
|| was not re-defined. It is a new use of the character sequence when
it exists as the first non-whitespace character on a source code line,
and is not part of some other thing.
cout << "Understand?";
Best regards,
Rick C. Hodgin
[toc] | [prev] | [next] | [standalone]
Page 2 of 4 — ← Prev page 1 [2] 3 4 Next page →
Back to top | Article view | comp.lang.c
csiph-web