On 14/03/2019 12:50, Bart wrote:
> On 14/03/2019 09:11, David Brown wrote:
>> On 13/03/2019 22:37, Bart wrote:
>
>>> OK, I forgot that you are used to C where struct definitions can be all
>>> mixed up with variable declarations:
>>
>> Ah, you mean you forgot I am used to C where the language is specified,
>
> Where the language is more chaotic, and so you might expect others to be
> as well.
>
If you didn't start with the assumption that anything C does must be the
worst possible choice and viewed in the most negative light, then I
expect your programming life would be easier, your languages would be
better, and your Usenet discussions would be more friendly.
>> and I understand it - rather than being used to your personal language
>> which is known only to you, and where I have to guess given tiny
>> snippets of code and vague descriptions?
>
> The original point of my post was to show that sometimes, static typing
> can lead to tighter and less cluttered code. Usually the opposite is
> true.
That strikes me as an odd point to try to make. I don't see static or
dynamic typing as particularly relevant there. What usually makes more
of a difference is when you have explicit typing compared to implicit or
inferred typing.
> It didn't need an extensive tutorial on both languages used; they
> could even have been made up pseudo-code.
I didn't want a tutorial. You introduced the two concepts of "structs"
and "records" in your language, and then over the course of 3 or 4 posts
you have failed to explain the distinction. I think that is mainly
because you are so desperate to show that they are not C, rather than
trying to explain what they actually /are/ in your language. Perhaps if
you didn't include "look how evil C is" interjections at all
opportunities, you'd get time to talk about your own language.
(Comparisons with C, or other common programming languages, are fine.)
I am not interested in reading your documentation (not at the moment,
anyway). If you can't explain the difference in a couple of paragraphs
in a Usenet post, then maybe you don't have a clear idea yourself.
>
>>> (1) struct {int x,y;}; // defines nothing
>>> (2) struct T {int x,y;}; // defines struct tag T
>>> (3) struct {int x,y;} A; // defines variable A
>>> (4) struct U {int x,y;} B; // struct tag U and variable B
>>> (5) typedef struct {int x,y;}; // nothing
>>> (6) typedef struct V {int x,y;}; // struct tag V
>>> (7) typedef struct W {int x,y;} C; // struct tag W, usertype C
>
>> But in all your efforts to try to show that C is complicated (it isn't)
>> or mixed up (it isn't), you managed to miss one form:
>>
>> (8) typedef struct { int x, y; } D;
>>
>> That is the form I use for defining types. I don't bother giving struct
>> tags unless the type will be recursive.
>
> I've numbered the examples (1) to (8) including yours. Here's how I
> define those examples in my static language (that one doesn't have the
> confusion between 'static' and 'record'); I use the more compact (...)
> delimiters:
It would again help if you stick to /one/ of your languages. If you
have reason to distinguish them or compare them, then at least give them
names.
>
> (1) Not valid
>
> (2) record T = (int x,y) # defines type not a tag
>
> (3) record T = (int x,y) # *must* have a name for A's type
> T A # now declare the variable A
>
> (4) record U = (int x,y) # define type name not tag
> U B # define variable B of type U
>
> (5) Not valid
>
> (6) record V = (int x,y) # define type not tag
>
> (7) record C = (int x,y) # define type name; discard 'tag'
>
> (8) record D = (int x,y)
>
Why not just say something like :
A "record" is a user-defined structure type holding data member fields.
You define a record type like this:
record T = (int x, y)
In this language, you must define and name types before using them - you
can't use unnamed types or define them on the fly, and you can't use the
type to declare variables until the record definition is complete.
To me, that is clear and simple. (It still doesn't distinguish between
"struct" and "record", but maybe that is not part of this language.)
> Where the C did something useful, notice that the versions here are all
> completely consistent: define a type (all exactly the same way) and
> define a variable.
>
>> (And because C is flexible, there
>> is nothing stopping you writing your own code as though the combinations
>> you dislike were not allowed.)
>
> That would be /my/ code. Everyone else /could/ be using a bad style and
> that has to be considered.
That's because the whole programming world is against you, and everyone
writes their C code with the specific aim of irritating you personally.
And since we are talking mainly about your own private languages that no
one else will ever see or use, surely the C comparison would be to C
code that you write yourself, not to C code written by others?
> Even you considered that my examples may have
> been declaring variables not types, because /C/ allows variables to be
> declared of anonymous struct types.
>
You gave two completely different looking syntaxes:
type ws_systemtime = struct ...
record huffnode =
It is entirely reasonable to assume they do two completely different
things - like declaring a type, and declaring a variable. And with
dynamic typing, it is entirely reasonable to suppose that fields can be
added to an instance of the type, rather than just to the type
definition (you can do that with Python, for example).
My question was not based on what C allows, because we were talking
about /your/ language, not C. My question was based on the assumption
that your language was reasonable and logical, and that you might have
been flexible regarding dynamic types. Was that an unwarranted assumption?
>
>> But why do you have wildly different syntax for the two ways to declare
>> user types?
>>
>> type ws_systemtime = struct ...
>>
>> record huffnode = ...
>>
>> Why not
>>
>> type huffnode = record ...
>>
>> or
>>
>> struct ws_systemtime = ...
>>
>> Surely that would be more consistent?
>
> <Shrug> I used to have only 'type'. Then I experimented with 'record'
> having a dedicated syntax. That seemed to work, so I might roll it out
> to 'struct'. (My new language will probably use 'record' for a 'flat'
> struct-like aggregate type, and 'class' for a higher level, managed
> version.)
So really, your language here - that is /so/ much clearer than C - is
very much in flux, with a jumble of syntaxes made up as you go along?
>
>>
>>> Individual instances
>>> can be created like this:
>>>
>>> a := new(ws_systemtime)
>>>
>>> or:
>>>
>>> b := huffnode(0,0,0,0)
>>
>> Again, why the different syntaxes?
>
> Why does C? In C you do:
>
> static systemtime A; # create A initialised to zeros
> static huffnode B = {0,0,0,0}; # create B initialised to zeros
I know the differences between these, and why they are there - as does
anyone who knows C. So why are you asking about C? I am asking about
/your/ language, because /you/ are the only one who knows it.
How about you start trying to answer questions about your language with
answers about your language, rather than more desperate attacks on C?
>
> In a dynamic language, you need way to assign a value of a certain type,
> and the generic way of doing that is with new(), but there need to be
> alternatives:
>
> a := new(list,6,77) # 6 elements all initialised to 77
> a := (77,77,77,77,77,77) # same thing
>
> b := new(list,10 million) # 10M elements all set to 'void'
> b := (void,void,void,... # this could take some time to type
> b := (void,)*10 million # alternative
>
> c := ???
> c := (10,20,30,40,50,60)
>
> Here this can't be done with 'new', as new doesn't allow the contents to
> be enumerated. (Although it is trivial to write a user-function that
> does exactly that.)
>
> d:= new(array,byte,'A'..'Z') # a 26-element byte-array indexed
> # from 65 to 90 ('A' to 'Z')
> d:= ???
None of that answers my question.
I asked you why you gave different syntaxes here. I asked you if they
had different meanings - in particular, if the space for the object
itself is allocated in a different way. You haven't given any
explanation for the difference, or any reason why you picked one syntax
for one type of variable and the other syntax for the other type of
variable. You haven't said how they are allocated. You haven't said
what "new" means in your language - you just seem to assume it obvious.
>
> Here there is no tidy constructor syntax to specify the same. However,
> this is possible:
>
> type T = ['A'..'Z']byte
> d := new(T)
> d := T(1,2,3,... 26) # there must be 26 elements
>
> As well as doing it via a user-function.
>
> It's all useful diversity, but still based on only two main features:
>
> x := new(T,...) # use new (just a function really)
> y := T(....) # use a constructor for aggregate types
> z := T(a) # That syntax is also type conversion
>
>
>> (If you want to stretch your brain a little, C++17 has not only static
>> type-safe union types std::variant, but the /static/ type-safe generic
>> std::any type. Don't ask me how these are implemented, especially
>> std::any - it is C++ magic beyond the understanding of most C++ experts.
>
> My new hybrid language will attempt something similar:
>
> variant a,b,c # can assume any type
> println a,b,c # display void void void
>
> Which allow some odd-looking things:
>
> a := a[i] # works when a is a list
> a := a^ # (deref) works when a is a pointer
> a := (a,a,a,a,a) # etc
>
> Because normal static typing rules don't apply.
>
This can be handled fine with static typing, using two points:
1. Allow variable definition to use type deduction or type inference
from the initialiser to determine the type. That is like "auto" in
C++11, or "let" in Ocaml. Here, you are allowing it without needing a
keyword at all - perhaps using := for declaring and initialising data,
distinct from = for assignment.
2. Allow variables with the same name to be re-declared, replacing the
old variable within the same scope.
> I'm fairly confident I can make it work without getting into C++
> complexities.
It's possible.
All the complexities in C++ are there for a reason. Sometimes that
reason is for backwards compatibility with C and C++, resulting in a
language that is more awkward than one that is designed from scratch to
have the same features. That kind of complexity you should be able to
avoid.