From: Dmitry A. Kazakov on
On Thu, 12 Aug 2010 15:56:41 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox(a)dmitry-kazakov.de> wrote in message
> news:1spow9sibnv6l.ci558lff75c8$.dlg(a)40tude.net...
>> On Wed, 11 Aug 2010 18:18:48 -0500, Randy Brukardt wrote:
>>
>>> "Dmitry A. Kazakov" <mailbox(a)dmitry-kazakov.de> wrote in message
>>> news:iv3qwjogornz$.1s8kq0yfl2wxl.dlg(a)40tude.net...
>>> ...
>>>> Conversion mess is what we already have right now. The point is that "+"
>>>> is
>>>> well-defined and meaningful for octets, but it is not closed in there.
>>>> Why
>>>>
>>>> function "**" (Left : T; Right : Natural) return T;
>>>> function S'Pos(Arg : S'Base) return universal_integer;
>>>> ...
>>>>
>>>> are OK and "+" is not?
>>>
>>> The first has the same operand and result type (the power operand is
>>> something else and not really part of the operator IMHO).
>>
>> What is the difference between "**" and "+"? It must be a language one,
>> because semantically sum of octets is not an octet.
>
> Octets don't have a sum, "sum of octets" is meaningless. It's like talking
> about the "sum of sand". They're just buckets.

The content of the bucket does have sum. Compare it with the elements an
integer array. According to the logic since array elements are buckets you
cannot sum integer elements.

> (By "octet" here I mean the
> same concept that Ada calls Stream_Elements, other than with a fixed size.)

1. This is not the way octets are used in communication applications.

2. If the idea of opaque container is pushed to its end, octet must have no
"and", "or", bit extraction operations either. They also presume some way
octets can be manipulated and interact with other types (like Boolean).

>>> The second is the
>>> long winded name for a conversion operator - it implies no semantic change.
>>> I'm arguing that operations like S'Pos would be better having a common name
>>> like "#" rather than a host of specialized names.
>>
>> Huh, and these must be a type conversions too:
>>
>> function S'Exponent (X : T) return universal_integer;
>> S'Length
>> A'Length (N)
>> ...
>
> Nope, these have semantics. Of course, the boundary is a gray area.

? semantics = meaning. Why do we need things without meaning = meaningless
things?

>>>> 1. What is this else?
>>>
>>> Huh? This doesn't parse.
>>
>> The above looks like math to me. You take octet arguments and compute some
>> results using arithmetic operations.
>
> The octets are converted to some other type that has math. There is no
> built-in relationship between the octet and the type with the math;

Built-in = language defined? But Ada does not define Octet.

> it has to be explicitly defined.

Yes, any operation has to be defined explicitly if not inherited.

>> I see. No, that is a wrong way IMO. The right one is interfaces. If you
>> want S be like T, derive S from T. If you don't like the implementation of
>> T, inherit only the interface of. You should never have a need in explicit
>> type conversions in a properly designed program.
>
> That way lies madness. You would have to give types properties that they
> have no reason to have (like "sum of octets").

The semantics is to be defined by the programmer.

> And if you do that, you now
> have a lot more chances for error (such as adding octets that are used to
> hold character values and not integers).

Yes, when implementing a communication protocol, there is no such things as
characters or integers, only octets. This is independent on the octet
operations. Compare it with address arithmetic. You can sum address of a
task with the address of an employee record. Does it mean that there has to
be no address arithmetic?

> Octets are by their nature an
> untyped bucket with no semantics; there has to be a conversion operation
> (like "#" above or S'Read in Ada) to some type with semantics for it to be
> meaningful.

No, that is impossible, because 1) there is no such conversion in almost
any case. Other objects are represented by collections of octets
interlinked in a very complex way. A simple conversion operation is
absolutely unsuitable abstraction for this. 2) You are talking about an
interface, (where however there should be no octets visible at all, but
streams, files etc), I am talking about implementation of such an
interface. There should be no conversions at any abstraction level.

>>> That's the point: in Ada, type conversions are *not* functions, they're a
>>> built-in gizmo [including some attributed]; by naming them "#" we would
>>> allow unifying them with functions.
>>
>> I would prefer to eliminate them altogether. Conversions are always bad.
>
> I strongly disagree. Some things are best modeled with little or no explicit
> semantics (such as a raw stream), and you must have conversions to get to
> real semantics. Indeed, *not* having using conversions in that case is
> misleading; you're applying improper semantics to the operation.

type Text_Stream is new Raw_Stream with private;

What is wrong with that?

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
From: Natacha Kerensikova on
On Aug 12, 10:45 pm, Ludovic Brenta <ludo...(a)ludovic-brenta.org>
wrote:
> The other notations:
>
> (tcp-connect ((host foo.example) (port 80)))
>
> and
>
> (tcp-connect (host foo.example) (port 80))
>
> are shorthand for that.

What bother me in this is that I feel those are two different objects.

I won't go into writing explicit cons pairs again, this is quite
unreadable. So I'll go for an ASCII-art representation, I hope it
won't be scrambled (if so please tell me, I'll try to come up with a
textual representation). Let L and A represent nodes, respectively
lists and atoms, vertical lines for "next in list", "brother" or
"cons" relations, and horizontal lines for "first child of list" or
"atom contents" relations.

Consider these two objects:

L--A--tcp-connect
|
L--A--host
| |
| A--foo.example
|
L--A--port
|
A--80

and:

L--A--tcp-connect
|
L--L--A--host
| |
| A--foo.example
|
L--A--port
|
A--80

I'm sure we can agree on the fact that these are two different and non-
equivalent objects: not the same topology and not even the same number
of nodes. So I'd say a proper S-expression library has to be able to
deal with both of them without mixing them up.

However, by considering as equivalent the two representations quoted
above, I'm afraid you might mixing these two object during encoding or
decoding.

Or have I misunderstood again?



Natacha
From: Natacha Kerensikova on
On Aug 13, 1:26 am, Shark8 <onewingedsh...(a)gmail.com> wrote:
> I took a bit of a stab at writing an SExpression handler, note that
> it's not a parser [text-file -> SExpression] but rather what (I think)
> you were terming in-memory.

Indeed, that's what my idea of my still-unnamed in-memory S-expression
object package would look like.

What I find surprising is that you seem to include type information in
the Node type (which actually represent a S-expression atom, while S-
expression nodes usually include lists too). Is it a typical Ada way
of doing it?

I find it surprising because the underlying S-expression format (as
standardized by Rivest, I know almost nothing about cons pairs or
lisp) cannot encoding that information. I would expect a S-expression
object in memory to reflect only what can be encoded to and decoded
from S-expression files.

In fact, one can consider S-expressions as a heterogeneous container,
in that each atom can represent an object of any type (while losing
the type information, which has to be retrieved from somewhere else),
in contrast to thing like vectors, whose items are all of the same
type. Does anybody know an example of heterogeneous container in Ada?
I'm not sure how Ada generics can be leveraged in such a case.

Another interesting point is that you chose arrays to represent S-
expression lists. Your code seems currently unable to represent empty
lists (which are legal at least in Rivest's S-expressions) but I guess
I can't be too difficult to correct. But it raises the question of
array vs linked list for a S-expression object implementation.

I'm not sure S-expressions would ever be used in a time-critical
application, so the usual argument of cache-friendliness of arrays is
pretty weak here. S-expressions are meant to be used for I/O where the
bottleneck is most likely to be.

Ada arrays are statically sized, which can be an issue for parsing,
because S-expression format doesn't encode list length, so a list has
to be built by pushing nodes one after the other until encountering
the end-of-list marker. But I think that should be easily worked
around by using vectors for unfinished S-expression lists, and once
the list is completely parsed build the array from the vector, and
reset the vector for further list parsing.

However for S-expression objects dynamically created into memory, the
static size of arrays might make some operations much less efficient
than with linked lists.

Any idea I'm missing about this implementation choice? Would it be
worth to try and make such a package generic over the container type
(array vs linked list vs something else?)?


Thanks for your code example,
Natacha
From: Ludovic Brenta on
Natacha Kerensikova wrote on comp.lang.ada:
> On Aug 12, 10:45 pm, Ludovic Brenta <ludo...(a)ludovic-brenta.org>
> wrote:
>> The other notations:
>>
>> (tcp-connect ((host foo.example) (port 80)))
>>
>> and
>>
>> (tcp-connect (host foo.example) (port 80))
>>
>> are shorthand for that.
>
> What bother me in this is that I feel those are two different objects.
>
> I won't go into writing explicit cons pairs again, this is quite
> unreadable. So I'll go for an ASCII-art representation, I hope it
> won't be scrambled (if so please tell me, I'll try to come up with a
> textual representation). Let L and A represent nodes, respectively
> lists and atoms, vertical lines for "next in list", "brother" or
> "cons" relations, and horizontal lines for "first child of list" or
> "atom contents" relations.
>
> Consider these two objects:
>
> L--A--tcp-connect
>    |
>    L--A--host
>    |  |
>    |  A--foo.example

This part cannot exist: the second L cannot have more than 2 children;
here you gave it three (A, A and the next L). The dot notation would
have prevented that mistake :)

>    |
>    L--A--port
>       |
>       A--80
>
> and:
>
> L--A--tcp-connect
>    |
>    L--L--A--host
>       |  |
>       |  A--foo.example
>       |
>       L--A--port
>          |
>          A--80

This one is the only correct topology.

--
Ludovic Brenta.
From: Natacha Kerensikova on
On Aug 13, 12:25 am, "Jeffrey R. Carter"
<spam.jrcarter....(a)spam.acm.org> wrote:
> Kerensikova (or is it Porté?)

It's both ;-) One of them is my real-life last name, as can be found
on my ID or on copyright notices, while the other is a pseudonymous
last name I've been using over the internet for something like a
decade now. While it was never intended to more than a thin pseudonym,
it was supposed to require a little more research to make the
connection, here I just messed up with Google accounts (I really hate
these browser interfaces, and now it makes me hate them even more, I
wish I could find a NNTP server and a real user-friendly text-mode
news reader).

> provided a more detailed grammar (using the
> trailing '*' from regexps rather than {}) with some additional options.

Is one of them more standard than the other? While I'm very familiar
with regex, I only have a few theoretical notions about grammar, and
almost nothing as practical experience with real grammar formats.

> >http://en.wikipedia.org/wiki/S-expression#Definition
>
> But maybe we're both wrong.

I can assure you what I'm doing is completely conform with Rivest's
standard proposition. I don't know how come it has not reached the
status of full-fledged RFC (while real RFCs like SPKI do depend on
it), but I'm using it as if it had. I only dropped the "display hint"
stuff from the format, because I find it little to no use, while it
introduces quite a bit of complexity.

However I have no idea how things look like from a lisp point of view.


Hoping this helps,
Natacha
First  |  Prev  |  Next  |  Last
Pages: 20 21 22 23 24 25 26 27 28 29 30 31 32 33
Prev: GPRbuild compatibility
Next: Irony?