Stephen Pelc <stephen@vfxforth.com> writes:[...]
However, higher level source code has been much
in demand. An example is Nick Nelson's value flavoured structures,
which are of particular merit when converting code from 32 bit to
64 bit host Forths.
Gforth has worked on 64-bit hosts since early 1996, and I found that
Forth code tends to have fewer portability problems between 32-bit and
64-bit platforms than C code, and that's not just my code, the
applications in appbench and many others are also quite portable.
A major merit for value-flavoured structures is that you can change
the field size (e.g, from 1 byte to 2 bytes or vice versa) without
changing all the code accessing those fields. That's independent of
cell size.
For example, it's impossible to change n to d, n to r, or vice versa,
without changing all the code accessing those fields.
Similar for the word `to` — `to` applies to the words created with
`value`, `fvalue`, `2value`. But the source code around `to foo` (and
`foo`) depends on the kind of `foo`, so the kind of `foo` cannot be
changed without changing the source code around where it is used.
Higher level (more polymorphic) source code in Forth is possible when
all values are boxed [1]
I don't know what compiler you use, but my values and locals
are certainly not boxed. TO et al (+TO *TO := *= ++ += *+) will
inspect their type and generate the appropriate machine code
without me having to change the source code if I change the type.
On Fri, 27 Sep 2024 8:15:48 +0000, Ruvim wrote:
For example, it's impossible to change n to d, n to r, or vice versa,
without changing all the code accessing those fields.
Similar for the word `to` — `to` applies to the words created with
`value`, `fvalue`, `2value`. But the source code around `to foo` (and
`foo`) depends on the kind of `foo`, so the kind of `foo` cannot be
changed without changing the source code around where it is used.
Higher level (more polymorphic) source code in Forth is possible when
all values are boxed [1]
I don't know what compiler you use, but my values and locals
are certainly not boxed. TO et al (+TO *TO := *= ++ += *+) will
inspect their type and generate the appropriate machine code
without me having to change the source code if I change the type.
I said about the source code *around* the usage places.
On Fri, 27 Sep 2024 12:27:18 +0000, Ruvim wrote:
I said about the source code *around* the usage places.
I see. Forth has only type-specific - or should one rather
say - stack-specific operators.
Introduce variant data-types, as some BASIC compilers have,
you really have to invent a new 'Forthish' dialect.
Probably useless for embedded applications.
Such dialects, or better said, descendants, already exist.
For example: Factor, StrongForth.
Probably useless for embedded applications.Agreed.
On 2024-09-27 16:46, minforth wrote:
...
Probably useless for embedded applications.
Agreed.
Ruvim <ruvim.pinka@gmail.com> writes:
Such dialects, or better said, descendants, already exist.
For example: Factor, StrongForth.
Probably useless for embedded applications.Agreed.
Factor is sort of a Lisp dialect that is garbage collected, I think. So maybe
not great for embedded. StrongForth, I thought, was like regular Forth but with a type system. That shouldn't be a problem unless there are other issues. Ada is strongly typed, and C++ is sort-of-strongly typed, and both are used in embedded apps all the time.
Is it not the endless comparison between forth and other languages
that invites all these 'innovations'?
Ruvim <ruvim.pinka@gmail.com> writes:
Such dialects, or better said, descendants, already exist.
For example: Factor, StrongForth.
Probably useless for embedded applications.Agreed.
Factor is sort of a Lisp dialect that is garbage collected, I think. So maybe
not great for embedded. StrongForth, I thought, was like regular Forth but >with a type system. That shouldn't be a problem unless there are other >issues. Ada is strongly typed, and C++ is sort-of-strongly typed, and both >are used in embedded apps all the time.
A strong type system is not a problem for embedded applications, as long
as there is a means to defeat the type system.
Ada was designed with this in mind, making distinction between safe and unsafe modules. Remember that c++ was an afterthought after c that was
not well designed in the first place.
Strong typing can be annoying. I remember wasting time passing a filename
to function that expected a `const char *` or something, and it is
by no means obvious what you have to do, so you are lured into casting.
A lot of people do not understand that casting is a means to defeat the
type system, so that you loose the advantages.
Rust has unsafe modules but I don't remember Ada having them. Ada does
have an Unchecked_Conversion function but I don't know where this is
really needed or how well specified it is in the language standard.
On 2024-09-15 20:16, Anton Ertl wrote:
A major merit for value-flavoured structures is that you can change
the field size (e.g, from 1 byte to 2 bytes or vice versa) without
changing all the code accessing those fields. That's independent of
cell size.
Yes, you can change the field size, but only as far as its value
occupies the same number of a stack items and the stack is the same.
Similar for the word `to` - `to` applies to the words created with
`value`, `fvalue`, `2value`. But the source code around `to foo` (and
`foo`) depends on the kind of `foo`, so the kind of `foo` cannot be
changed without changing the source code around where it is used.
Introduce variant data-types, as some BASIC compilers have,
you really have to invent a new 'Forthish' dialect. Probably
useless for embedded applications.
minforth@gmx.net (minforth) writes:
Introduce variant data-types, as some BASIC compilers have,
you really have to invent a new 'Forthish' dialect. Probably
useless for embedded applications.
Joerg Voelker works on embedded projects and found value-flavoured
fields useful already in 2017 <https://wiki.forth-ev.de/doku.php/events:tagung-2017:forth-in-grossen-projekten>.
Nick Nelson works on (bigger) embedded projects and also finds value-flavoured fields useful. See <http://www.euroforth.org/ef22/papers/nelson-values.pdf> <http://www.euroforth.org/ef22/papers/nelson-values-slides.pdf> <https://www.youtube.com/watch?v=UHcLqxG7UI4>
Ruvim <ruvim.pinka@gmail.com> writes:
On 2024-09-15 20:16, Anton Ertl wrote:
A major merit for value-flavoured structures is that you can change
the field size (e.g, from 1 byte to 2 bytes or vice versa) without
changing all the code accessing those fields. That's independent of
cell size.
Yes, you can change the field size, but only as far as its value
occupies the same number of a stack items and the stack is the same.
Yes. But you can switch between different sizes that all fit into a
cell, or between different memory sizes of floats without changing the
rest of the code.
Similar for the word `to` - `to` applies to the words created with
`value`, `fvalue`, `2value`. But the source code around `to foo` (and
`foo`) depends on the kind of `foo`, so the kind of `foo` cannot be
changed without changing the source code around where it is used.
That's just as for reading the value-flavoured field; if a field
pushes one cell, TO to the field also consumes one cell; likewise for
float fields.
1. From the lexical point of view, "to foo" and "set-foo" are almost the >same. "to foo" can even be considered a separate fancy word with a
space in its name.
3. "set-foo" can be easily redefined (for example, if you want to check
the assigned value to prevent some bugs in advance).
"to foo" *cannot* be redefined. Although, one can redefine "to" to check
its argument and have a special action when its argument is "foo" — this >is very cumbersome.
4. "set-foo" can be accessed using qualified names, such as
mymodule::set-foo or mymodule( set-foo )
A variant like "to mymodule::foo" could work,
a variant like "to mymodule( set-foo )" cannot work.
Bottom line: I don't see any advantages in *using* a to-based setter
over a separate setter.
Ruvim <ruvim.pinka@gmail.com> writes:
1. From the lexical point of view, "to foo" and "set-foo" are almost the
same. "to foo" can even be considered a separate fancy word with a
space in its name.
Even closer: With the to-recognizer you can write ->FOO.
3. "set-foo" can be easily redefined (for example, if you want to check
the assigned value to prevent some bugs in advance).
"to foo" *cannot* be redefined. Although, one can redefine "to" to check
its argument and have a special action when its argument is "foo" — this >> is very cumbersome.
Wrong.
It can be defined: Gforth has SET-TO <https://gforth.org/manual/Words-with-user_002ddefined-TO-etc_002e.html> which allows you to define what TO FOO does.
If you mean that a standard program cannot define it, true,
but that's just a matter of what is currently standardized.
4. "set-foo" can be accessed using qualified names, such as
mymodule::set-foo or mymodule( set-foo )
A variant like "to mymodule::foo" could work,
a variant like "to mymodule( set-foo )" cannot work.
Let's see:
[~/gforth:152808] gforth
Gforth 0.7.9_20241003
Authors: Anton Ertl, Bernd Paysan, Jens Wilke et al., for more type `authors' Copyright © 2024 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>
Gforth comes with ABSOLUTELY NO WARRANTY; for details type `license'
Type `help' for basic help
vocabulary voc ok
also voc definitions ok
5 value val ok
previous ok
voc:val ok 1
. 5 ok
7 to voc:val \ <---------- ok
also voc ok
val . 7 ok
previous ok
8 ->voc:val \ <----------- ok
voc:val . 8 ok
3 +>voc:val \ <----------- ok
voc:val . 11 ok
I pointed out exactly where TO VOC:VAL, ->VOC:VAL and +>VOC:VAL occur.
No not only can it work, it already works in Gforth. And here the
"standard program excuse" does not apply, because neither your
qualification syntax nor Gforth's scope-recognizer are standardized.
Bottom line: I don't see any advantages in *using* a to-based setter
over a separate setter.
However, lots of Forth programmers have defined VALUEs, and barely any
have defined getters and setters.
The discussions have been aboyt
values vs. variables, not about values vs. getters and setters.
On 2024-10-04 15:52, Anton Ertl wrote:...
It can be defined: Gforth has SET-TO
I wonder why a kind of "TO" is not used to set this field/property, and >*maybe* a kind of "ACTION-OF" to get this property.
However, lots of Forth programmers have defined VALUEs, and barely any
have defined getters and setters.
Do you mean that this is due to some advantages in *using*?
I think, this is because `VALUE` (and co.) is a very old technique that
is provided out of the box by many systems.
In contrast, to use
separate getters and setters you need to create your own tool to define >them.
The discussions have been aboyt
values vs. variables, not about values vs. getters and setters.
This shows that some people don't like the to-based approach.
I seen that some implementers provide "value" and "to" only for third
party programs and don't use them themselves.
On 4/10/2024 2:32 am, Anton Ertl wrote:
minforth@gmx.net (minforth) writes:
Introduce variant data-types, as some BASIC compilers have,
you really have to invent a new 'Forthish' dialect. Probably
useless for embedded applications.
Joerg Voelker works on embedded projects and found value-flavoured
fields useful already in 2017
<https://wiki.forth-ev.de/doku.php/events:tagung-2017:forth-in-grossen-projekten>.Nick Nelson works on (bigger) embedded projects and also finds
value-flavoured fields useful. See
<http://www.euroforth.org/ef22/papers/nelson-values.pdf>
<http://www.euroforth.org/ef22/papers/nelson-values-slides.pdf>
<https://www.youtube.com/watch?v=UHcLqxG7UI4>
I wonder whether classic structures fit the forth paradigm? Whether by >chance or lack of schooling they seem to have passed me by.
According to Moore:
"Forth is definitions. If you have a lot of small definitions you are
writing Forth."
Structures claim to avoid 'magic numbers'. But are numbers 'magic' when
the name of the definition containing them identifies what they are?
Example:
\ copy memory data (ofs) to target (a)
: SET.S ( a ofs -- ) dbuf + count rot >target place ;
: SET.W ( a ofs -- ) dbuf + @ swap >target ! ;
: SET.B ( a ofs -- ) dbuf + c@ swap >target c! ;
hex
: THIL ( -- ) 1C2 5B set.s ; \ hilight video
: TNOR ( -- ) 1C8 61 set.s ; \ normal video
: TEOL ( -- ) 1BC 69 set.s ; \ clear to end-of-line
: TINS ( -- ) 1AE 6F set.s ; \ insert line
: TDEL ( -- ) 1B4 75 set.s ; \ delete line
: TCR ( -- ) 168 7B set.w ; \ # cols rows
decimal
\ modify data
: SET$ ( ofs size -- )
over .str change? if cr ." : " get$ rot !str end 2drop ;
: SET# ( ofs -- )
dup @byt . change? if ." : " get# swap !byt end drop ;
: ?DEL ( -- ) cr ." DELETE LINE command: " $75 5 set$ ;
: ?INS ( -- ) cr ." INSERT LINE command: " $6F 5 set$ ;
: ?EOL ( -- ) cr ." ERASE TO EOL command: " $69 5 set$ ;
: ?BOLD ( -- ) cr ." BOLD VIDEO command: " $5B 5 set$ ;
: ?NORM ( -- ) cr ." NORMAL VIDEO command: " $61 5 set$ ;
: ?ROWS ( -- ) cr ." Number of screen rows: " $7C set# ;
: ?COLS ( -- ) cr ." Number of screen cols: " $7B set# ;
Ruvim <ruvim.pinka@gmail.com> writes:
On 2024-10-04 15:52, Anton Ertl wrote:...
It can be defined: Gforth has SET-TO
I wonder why a kind of "TO" is not used to set this field/property, and
*maybe* a kind of "ACTION-OF" to get this property.
Interesting idea. Maybe in some future version.
However, lots of Forth programmers have defined VALUEs, and barely any
have defined getters and setters.
Do you mean that this is due to some advantages in *using*?
I think, this is because `VALUE` (and co.) is a very old technique that
is provided out of the box by many systems.
Yes. Writing getters and setters is also provided out of the box.
variable addr-x
: x addr-x @ ;
: set-x addr-x ! ;
For some reason, people have not written getters and setters.
The lack of flexibility of standard TO has not deterred them from
using that.
In contrast, to use
separate getters and setters you need to create your own tool to define
them.
Obviously not, see above.
What tool do you have in mind?
The discussions have been aboyt
values vs. variables, not about values vs. getters and setters.
This shows that some people don't like the to-based approach.
Does it? Are they using getters and setters instead? No.
I seen that some implementers provide "value" and "to" only for third
party programs and don't use them themselves.
Which ones? Typing WHERE TO right after startup in Gforth and in
SwiftForth shows a number of uses of TO in both systems.
On 2024-10-04 22:04, Anton Ertl wrote:
Ruvim <ruvim.pinka@gmail.com> writes:
On 2024-10-04 15:52, Anton Ertl wrote:...
It can be defined: Gforth has SET-TO
I wonder why a kind of "TO" is not used to set this field/property, and
*maybe* a kind of "ACTION-OF" to get this property.
Interesting idea. Maybe in some future version.
What advantages do you see in *using* the to-based setters?
int: noop
comp: default-name>comp
string: named>string
link: named>link ok
The lack of flexibility of standard TO has not deterred them from
using that.
This statement contains the logical fallacy "Survivorship bias" [1].
There are different use cases. In some use cases the discussed
flexibility is not needed, in other — it is needed.
For example, it could be a defining word "val" that is used as "val x"
and creates the getter "x" and the setter "set-x".
Such a word "val" can be defined like this:
[undefined] name> [if]
: name> ( nt -- xt )
name>interpret dup if exit then
drop [: -14 throw ;]
;
[then]
: val ( "name" -- )
create 0 , [: does> @ ;] execute
0. <# latest-name name>string holds s" set-" holds #>
['] : execute-parsing
latest-name name> >body lit,
postpone ! postpone ;
;
\ Re "latest-name" see [2]
\ test
t{ val x -> }t
t{ x -> 0 }t
t{ 3 set-x -> }t
t{ x -> 3 }t
\ Let's redefine the setter "set-x"
: set-x ( u -- )
dup 10 u> abort" too big value for x"
set-x
;
t{ 4 set-x x -> 4 }t
t{ 11 ' set-x catch 2drop x -> 4 }t
Could you show how to implement that in Gforth when the to-based setter
"to x" is used?
NB: the solution must not change the original "x", it must redefine "x".
The difference is that the new definition *can* be in a different word
list, in which case both definitions (old and new) can be used depending
on the context.
This shows that some people don't like the to-based approach.
Does it? Are they using getters and setters instead? No.
How do you know this?
Ruvim <ruvim.pinka@gmail.com> writes:
On 2024-10-04 22:04, Anton Ertl wrote:
Ruvim <ruvim.pinka@gmail.com> writes:
On 2024-10-04 15:52, Anton Ertl wrote:...
It can be defined: Gforth has SET-TO
I wonder why a kind of "TO" is not used to set this field/property, and >>>> *maybe* a kind of "ACTION-OF" to get this property.
Interesting idea. Maybe in some future version.
Thinking some more about it, better not:
SET-TO SET-OPTIMIZER etc. all work on the latest definition.
The methods that they set work on an NT or XT passed on the stack.
The usual behaviour of defer-flavoured words is that the context is
the same. If you have
defer d
' foo is d
action-of d
That's always the same global D. For a defer-flavoured field,
likewise:
0
value: vf
defer: df
constant mystruct
create foo mystruct allot
1 foo to vf
' . foo is df
foo vf .
2 foo df
So having TO TO instead of SET-TO would disobey this principle.
For COMPILE, there is the additional problem that it is a deferred
word, so when you do "IS COMPILE," you change the behaviour for all
uses of "COMPILE,", not just of the latest definition. The actual
method of each definition is called OPT-COMPILE,.
Ruvim <ruvim.pinka@gmail.com> writes:
What advantages do you see in *using* the to-based setters?
Over using SET-... words?
1) It's a popular and convenient mechanism.
2) I can find out the setter from looking at the central word:
``vf .hm
\ output:
opt: $7F43EB229B98
to: $7F43EB229BE0
extra: $7F43EB229B60
int: noop
comp: default-name>comp
string: named>string
link: named>link ok
Ok, $7F43EB229BE0 is not very informative, but I can still make use of
that:
$7F43EB229BE0 xt-locate
struct-val.fs:88
...
cell ' aligned ' @ !a-table wrap+value: value: ( u1 "name" -- u2 ) \ gforth-experimental
...
[...]For example, it could be a defining word "val" that is used as "val x"
and creates the getter "x" and the setter "set-x".
\ Let's redefine the setter "set-x"
: set-x ( u -- )
dup 10 u> abort" too big value for x"
set-x
;
t{ 4 set-x x -> 4 }t
t{ 11 ' set-x catch 2drop x -> 4 }t
Could you show how to implement that in Gforth when the to-based setter
"to x" is used?
: to-x ( u xt -- )
>r dup 10 u> abort" too big value for x" r> >body ! ;
to-table: x-table to-x
' >body x-table to-class: x-to
0 value x
' x-to set-to
4 to x x . \ prints "4"
11 to x
The last line produces the following error:
*the terminal*:13:7: error: too big value for x
11 to >>>x<<<
NB: the solution must not change the original "x", it must redefine "x".
The difference is that the new definition *can* be in a different word
list, in which case both definitions (old and new) can be used depending
on the context.
Let's see. To make it easier to see what is going on I use a
different name for the redefined word.
0 value y
synonym z y
' x-to set-to
4 to y
z . \ prints 4
11 to y
z . \ prints 11
11 to z \ aborts with "error: too big value for x"
For a bounds-checking TO I find this requirement strange, however.
Ruvim <ruvim.pinka@gmail.com> writes:[...]
On 2024-10-04 22:04, Anton Ertl wrote:
The lack of flexibility of standard TO has not deterred them from
using that.
This statement contains the logical fallacy "Survivorship bias" [1].
There are different use cases. In some use cases the discussed
flexibility is not needed, in other — it is needed.
That's a very Forthy way of looking at it. The usual argument for
getters and setters is that that flexibility might be needed in the
future, so you don't use a mechanism like variables or values that
does not provide this flexibility, in order to avoid having to change
all the places where the variable or value is used, and only have to
change the place where the getter and setter is defined.
In this
scenario value-flavoured words must not be used unless the flexibility
for TO is provided (i.e., they must not be used in standard Forth).
But yes, there are probably not many people with that mindset in the
Forth community.
Forth-94 seems to have had some of that, though,
with words like GET-CURRENT and SET-CURRENT instead of a (user)
variable CURRENT that had existing practice at the time. I wish they
had defined GET-BASE and SET-BASE instead of BASE.
Sysop: | DaiTengu |
---|---|
Location: | Appleton, WI |
Users: | 1,007 |
Nodes: | 10 (0 / 10) |
Uptime: | 201:58:47 |
Calls: | 13,143 |
Files: | 186,574 |
D/L today: |
587 files (134M bytes) |
Messages: | 3,310,214 |