Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.forth > #50166 > unrolled thread
| Started by | hughaguilar96@gmail.com |
|---|---|
| First post | 2016-08-15 23:10 -0700 |
| Last post | 2016-08-18 18:31 -0700 |
| Articles | 20 on this page of 45 — 12 participants |
Back to article view | Back to comp.lang.forth
the IS-A function hughaguilar96@gmail.com - 2016-08-15 23:10 -0700
Re: the IS-A function hughaguilar96@gmail.com - 2016-08-16 00:22 -0700
Re: the IS-A function hughaguilar96@gmail.com - 2016-08-16 14:01 -0700
Re: the IS-A function hughaguilar96@gmail.com - 2016-08-16 14:20 -0700
Re: the IS-A function JennyB <jennybrien@googlemail.com> - 2016-08-17 05:04 -0700
Re: the IS-A function hughaguilar96@gmail.com - 2016-08-17 10:52 -0700
Re: the IS-A function hughaguilar96@gmail.com - 2016-08-17 19:31 -0700
Re: the IS-A function anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2016-08-18 08:00 +0000
Re: the IS-A function JennyB <jennybrien@googlemail.com> - 2016-08-18 21:52 -0700
Re: the IS-A function Julian Fondren <julian.fondren@gmail.com> - 2016-08-17 07:11 -0700
Re: the IS-A function franck.bensusan@gmail.com - 2016-08-17 23:13 -0700
Re: the IS-A function hughaguilar96@gmail.com - 2016-08-18 11:59 -0700
Re: the IS-A function hughaguilar96@gmail.com - 2016-08-18 15:11 -0700
Re: the IS-A function franck.bensusan@gmail.com - 2016-08-18 23:14 -0700
Re: the IS-A function hughaguilar96@gmail.com - 2016-08-19 01:01 -0700
Re: the IS-A function franck.bensusan@gmail.com - 2016-08-19 03:14 -0700
Re: the IS-A function Ron Aaron <rambamist@gmail.com> - 2016-08-19 13:31 +0300
Re: the IS-A function Raimond Dragomir <raimond.dragomir@gmail.com> - 2016-08-19 03:39 -0700
Re: the IS-A function franck.bensusan@gmail.com - 2016-08-19 06:49 -0700
Re: the IS-A function lawrencedo99@gmail.com - 2016-08-19 14:55 -0700
Re: the IS-A function Paul Rubin <no.email@nospam.invalid> - 2016-08-19 14:57 -0700
Re: the IS-A function franck.bensusan@gmail.com - 2016-08-20 10:29 -0700
Re: the IS-A function Ron Aaron <rambamist@gmail.com> - 2016-08-20 20:35 +0300
Re: the IS-A function Paul Rubin <no.email@nospam.invalid> - 2016-08-20 10:53 -0700
Re: the IS-A function Julian Fondren <julian.fondren@gmail.com> - 2016-08-20 11:01 -0700
Re: the IS-A function Paul Rubin <no.email@nospam.invalid> - 2016-08-20 19:36 -0700
Re: the IS-A function Julian Fondren <julian.fondren@gmail.com> - 2016-08-20 20:15 -0700
Re: the IS-A function lawrencedo99@gmail.com - 2016-08-21 14:53 -0700
Re: the IS-A function Cecil Bayona <cbayona@cbayona.com> - 2016-08-19 08:28 -0500
Re: the IS-A function hughaguilar96@gmail.com - 2016-08-20 19:30 -0700
Re: the IS-A function Cecil Bayona <cbayona@cbayona.com> - 2016-08-20 22:20 -0500
Re: the IS-A function hughaguilar96@gmail.com - 2016-08-20 20:50 -0700
OOP (was: the IS-A function) Ron Aaron <rambamist@gmail.com> - 2016-08-21 07:21 +0300
Re: the IS-A function Mark Wills <markwills1970@gmail.com> - 2016-08-21 01:42 -0700
Re: the IS-A function Coos Haak <htrofhc@gmail.com> - 2016-08-21 14:16 +0200
Re: the IS-A function Mark Wills <markwills1970@gmail.com> - 2016-08-21 11:08 -0700
Re: the IS-A function Coos Haak <htrofhc@gmail.com> - 2016-08-21 21:25 +0200
Re: the IS-A function hughaguilar96@gmail.com - 2016-08-21 12:01 -0700
Re: the IS-A function hughaguilar96@gmail.com - 2016-08-18 17:08 -0700
Re: the IS-A function hughaguilar96@gmail.com - 2016-08-19 00:29 -0700
Re: the IS-A function hughaguilar96@gmail.com - 2016-08-28 11:01 -0700
Re: the IS-A function hughaguilar96@gmail.com - 2016-08-28 14:45 -0700
Re: the IS-A function Mark Wills <markwills1970@gmail.com> - 2016-08-18 02:22 -0700
Re: the IS-A function hughaguilar96@gmail.com - 2016-08-18 12:02 -0700
Re: the IS-A function hughaguilar96@gmail.com - 2016-08-18 18:31 -0700
Page 1 of 3 [1] 2 3 Next page →
| From | hughaguilar96@gmail.com |
|---|---|
| Date | 2016-08-15 23:10 -0700 |
| Subject | the IS-A function |
| Message-ID | <af44a9ce-4ab4-4a60-b6b1-5a1b8a2fe820@googlegroups.com> |
Doug Hoffman's FMS has IS-A so I decided to implement this too. It is in the novice-package now. I'm never going to have a HAS-A function though --- I don't think duck-typing is a good idea.
I'm dubious that IS-A is a good idea either --- normally you have some tag field that tells you what you have --- supporting IS-A makes every object one cell larger than it otherwise would be, although with today's huge RAM that shouldn't be an issue.
It was trivial to implement --- it took less than one hour to write and it worked the first time --- here it is:
0
w field .class-parent \ pointer to parent class \ must be first field
w field .class-size \ size of object
constant class-struct
\ Every object has a W field in front which is a pointer to the class-struct for its class.
create nada \ this is the parent class of classes that don't inherit anything
nil , \ .class-parent \ there is no parent
w , \ .class-size \ room for the object's pointer to its class-struct
: class ( -- class offset ) \ stream: class-name parent-name
create here \ -- class
' >body \ -- class parent
dup , \ -- class parent \ .class-parent
-1 , \ -- class parent \ .class-size this will get filled in by END-CLASS
.class-size @ ; \ -- class offset
: end-class ( class offset -- )
swap .class-size ! ;
: <new> ( class-xt -- object )
>body >r \ -- \ r: -- class
r@ .class-size @ alloc \ -- object
dup r@ .class-size @ erase \ zero out the object
r> over ! ; \ first field of object is pointer to class
: new ( -- adr ) \ stream: class-name
state @ if
postpone ['] postpone <new>
else
' <new>
then ;
immediate
: <is-a> ( object target-xt -- flag )
>body \ -- object target
swap @ \ -- target class
begin
2dup = if 2drop true exit then
@ \ -- target parent \ .class-parent is first field
dup 0= if 2drop false exit then
again ;
: is-a ( object -- ) \ stream: class-name
state @ if
postpone ['] postpone <is-a>
else
' <is-a>
then ;
immediate
[toc] | [next] | [standalone]
| From | hughaguilar96@gmail.com |
|---|---|
| Date | 2016-08-16 00:22 -0700 |
| Message-ID | <7d61195b-728f-4173-b9fa-102a7c924af5@googlegroups.com> |
| In reply to | #50166 |
On Monday, August 15, 2016 at 11:11:01 PM UTC-7, hughag...@gmail.com wrote:
> Doug Hoffman's FMS has IS-A so I decided to implement this too. It is in the novice-package now. I'm never going to have a HAS-A function though --- I don't think duck-typing is a good idea.
>
> I'm dubious that IS-A is a good idea either --- normally you have some tag field that tells you what you have --- supporting IS-A makes every object one cell larger than it otherwise would be, although with today's huge RAM that shouldn't be an issue.
>
> It was trivial to implement --- it took less than one hour to write and it worked the first time --- here it is:
>
>
> 0
> w field .class-parent \ pointer to parent class \ must be first field
> w field .class-size \ size of object
> constant class-struct
>
> \ Every object has a W field in front which is a pointer to the class-struct for its class.
>
> create nada \ this is the parent class of classes that don't inherit anything
> nil , \ .class-parent \ there is no parent
> w , \ .class-size \ room for the object's pointer to its class-struct
>
> : class ( -- class offset ) \ stream: class-name parent-name
> create here \ -- class
> ' >body \ -- class parent
> dup , \ -- class parent \ .class-parent
> -1 , \ -- class parent \ .class-size this will get filled in by END-CLASS
> .class-size @ ; \ -- class offset
>
> : end-class ( class offset -- )
> swap .class-size ! ;
>
> : <new> ( class-xt -- object )
> >body >r \ -- \ r: -- class
> r@ .class-size @ alloc \ -- object
> dup r@ .class-size @ erase \ zero out the object
> r> over ! ; \ first field of object is pointer to class
>
> : new ( -- adr ) \ stream: class-name
> state @ if
> postpone ['] postpone <new>
> else
> ' <new>
> then ;
> immediate
>
> : <is-a> ( object target-xt -- flag )
> >body \ -- object target
> swap @ \ -- target class
> begin
> 2dup = if 2drop true exit then
> @ \ -- target parent \ .class-parent is first field
> dup 0= if 2drop false exit then
> again ;
>
> : is-a ( object -- ) \ stream: class-name
> state @ if
> postpone ['] postpone <is-a>
> else
> ' <is-a>
> then ;
> immediate
Well, it occurs to me that somebody (Anton Ertl) will complain that I have STATE-smart words in here. So I upgraded the package slightly to not have STATE-smart words anymore. This is slightly shorter code:
0
w field .class-parent \ pointer to parent class \ must be first field
w field .class-size \ size of object
constant class-struct
\ Every object has a W field in front which is a pointer to the class-struct for its class.
create nada \ this is the parent class of classes that don't inherit anything
nil , \ .class-parent \ there is no parent
w , \ .class-size \ room for the object's pointer to its class-struct
: class ( -- class offset ) \ stream: class-name parent-name
create here \ -- class
' >body \ -- class parent
dup , \ -- class parent \ .class-parent
-1 , \ -- class parent \ .class-size \ this will get filled in by END-CLASS
.class-size @ \ -- class offset
does> ( -- adr ) \ this makes a new object (what was done by NEW previously)
>r \ -- \ r: -- class
r@ .class-size @ alloc \ -- object
dup r@ .class-size @ erase \ zero out the object
r> over ! ; \ first field of object is pointer to class
: end-class ( class offset -- )
swap .class-size ! ;
: object-size ( object -- size )
@ \ -- class
.class-size @ ; \ -- size
: <is-a> ( object target-xt -- flag )
>body \ -- object target
swap @ \ -- target class
begin
2dup = if 2drop true exit then
@ \ -- target parent \ .class-parent is first field
dup 0= if 2drop false exit then
again ;
: is-a ( object -- flag ) \ stream: target-class-name
' <is-a> ;
: [is-a] ( object -- flag ) \ stream: target-class-name
postpone ['] postpone <is-a> ;
[toc] | [prev] | [next] | [standalone]
| From | hughaguilar96@gmail.com |
|---|---|
| Date | 2016-08-16 14:01 -0700 |
| Message-ID | <9f5b652a-21bc-4b11-b8c9-0fc68b1aa714@googlegroups.com> |
| In reply to | #50166 |
On Monday, August 15, 2016 at 11:11:01 PM UTC-7, hughag...@gmail.com wrote: > Doug Hoffman's FMS has IS-A so I decided to implement this too. It is in the novice-package now. I'm never going to have a HAS-A function though --- I don't think duck-typing is a good idea. > > I'm dubious that IS-A is a good idea either --- normally you have some tag field that tells you what you have --- supporting IS-A makes every object one cell larger than it otherwise would be, although with today's huge RAM that shouldn't be an issue. > > It was trivial to implement --- it took less than one hour to write and it worked the first time --- here it is: > > > 0 > w field .class-parent \ pointer to parent class \ must be first field > w field .class-size \ size of object > constant class-struct > > \ Every object has a W field in front which is a pointer to the class-struct for its class. > > create nada \ this is the parent class of classes that don't inherit anything > nil , \ .class-parent \ there is no parent > w , \ .class-size \ room for the object's pointer to its class-struct > > : class ( -- class offset ) \ stream: class-name parent-name > create here \ -- class > ' >body \ -- class parent > dup , \ -- class parent \ .class-parent > -1 , \ -- class parent \ .class-size this will get filled in by END-CLASS > .class-size @ ; \ -- class offset > > : end-class ( class offset -- ) > swap .class-size ! ; > > : <new> ( class-xt -- object ) > >body >r \ -- \ r: -- class > r@ .class-size @ alloc \ -- object > dup r@ .class-size @ erase \ zero out the object > r> over ! ; \ first field of object is pointer to class > > : new ( -- adr ) \ stream: class-name > state @ if > postpone ['] postpone <new> > else > ' <new> > then ; > immediate > > : <is-a> ( object target-xt -- flag ) > >body \ -- object target > swap @ \ -- target class > begin > 2dup = if 2drop true exit then > @ \ -- target parent \ .class-parent is first field > dup 0= if 2drop false exit then > again ; > > : is-a ( object -- ) \ stream: class-name > state @ if > postpone ['] postpone <is-a> > else > ' <is-a> > then ; > immediate
[toc] | [prev] | [next] | [standalone]
| From | hughaguilar96@gmail.com |
|---|---|
| Date | 2016-08-16 14:20 -0700 |
| Message-ID | <88d81f07-03f4-4297-9e7e-953ac3bfeead@googlegroups.com> |
| In reply to | #50166 |
On Monday, August 15, 2016 at 11:11:01 PM UTC-7, hughag...@gmail.com wrote:
> Doug Hoffman's FMS has IS-A so I decided to implement this too. It is in the novice-package now. I'm never going to have a HAS-A function though --- I don't think duck-typing is a good idea.
>
> I'm dubious that IS-A is a good idea either --- normally you have some tag field that tells you what you have --- supporting IS-A makes every object one cell larger than it otherwise would be, although with today's huge RAM that shouldn't be an issue.
An argument that can be made against this system is that the first field of every object is now the pointer to the class of that object. The first field is faster than the rest (because the add of a zero offset gets optimized away), but now that is wasted on this pointer that is almost never used. For example, in LIST.4TH I had this:
0
w field .fore \ .FORE will be fast because it is in the front
constant list
Now with this new system I would have this:
class list nada
w field .fore
end-class
Now the .FORE no longer gets the optimization, although it is the field that really needs to be optimized because HOFs such as EACH etc. all access it inside of a loop.
> It was trivial to implement --- it took less than one hour to write and it worked the first time --- here it is:
Anyway, I made another upgrade. I now have a total of two hours invested in this code. These are the features I have now:
1.) With CLASS and END-CLASS the definition of a class is more readable than the old way in which I just used CONSTANT.
2.) The IS-A and [IS-A] functions tell you if an object is a member of a particular class or any of its parent classes.
3.) It is possible to make a new object in either the heap or the dictionary.
To make a new LIST object for the heap use: HEAP-NEW LIST
To make a new LIST object for the dictionary use: DICT-NEW LIST
4.) The CHILDLIKE and [CHILDLIKE] functions can be used to convert an object from one class into another class assuming that the new class is a child of the original class. This reallocates memory to make the new object big enough. This works for either heap or dictionary objects.
5.) I have error-checking now. If you try to use a class that isn't actually a class, this gets caught. Also, if you forget END-CLASS and your class is never initialized, this gets caught when you try to use the class.
6.) NADA will now abort if you try to use it to make an object, which doesn't make any sense.
7.) I have CLASS-SIZE now that provides the size of an object for that class. I'm not sure what the programmer would want this information for, but it was an easy feature to provide.
I may yet write that book that Cecil suggested: "ANS-Forth a Guide to Alternate Realities." It could be pretty much based on this code, providing some general-purpose data-structures. This is not the "Forth Way" according to the Forth-200x committee --- so this is an "alternate reality" --- purgatory for Forth programmers who refuse to accept the "Forth Way" and hence can't be considered to be real Forth programmers.
Anyway, here is the code (note that all of this requires the novice-package):
98769876 constant class-id \ used to make sure a class is actually a class; must be a distinctive value
0
w field .class-parent \ pointer to parent class \ must be first field
w field .class-size \ size of object
w field .class-id \ should always be CLASS-ID
constant class-struct
\ Every object has a W field in front which is a pointer to the class-struct for its class.
: check-class ( class -- )
.class-id @ class-id <> abort" *** tried to use a class that wasn't actually a class ***" ;
: create-nada ( -- ) \ create a class that has no parent
create
nil , \ .class-parent \ there is no parent
w , \ .class-size \ room for the object's pointer to its class-struct
class-id , \ .class-id \ this is for error-checking
does> ( -- )
true abort" *** it is illegal to make objects of class NADA ***" ;
create-nada nada \ NADA is the only class that has no parent
\ NADA is only available so it can be the parent of classes that have no parent.
\ It is not really a class that can be used as such.
' alloc constant heap-new \ give this to the class to get a new object in the heap
' concrete-alloc constant dict-new \ give this to the class to get a new object in the dictionary
: class-size ( class -- size )
.class-size @
dup 0< abort" *** CLASS-SIZE given a class that never had its .CLASS-SIZE field set by END-CLASS ***" ;
: object-size ( object -- size )
@ \ -- class
.class-size @ ; \ -- size
: class ( -- class offset ) \ stream: class-name parent-name
create here \ -- class
' >body \ -- class parent
dup check-class \ -- class parent \ make sure PARENT is a class
dup , \ -- class parent \ .class-parent
-1 , \ -- class parent \ .class-size \ this will get filled in by END-CLASS
class-id , \ -- class parent \ .class-id \ this is for error-checking
class-size \ -- class offset
does> ( 'alloc -- adr ) \ make a new object ( 'ALLOC is either HEAP-NEW or DICT-NEW)
>r \ 'alloc -- \ r: -- class
r@ class-size swap execute \ -- object
dup r@ class-size erase \ zero out the object
r> over ! ; \ first field of object is pointer to class
: end-class ( class offset -- )
over check-class \ make sure CLASS is a class
swap .class-size ! ;
: <<is-a>> ( class target -- flag )
swap \ target class
over check-class over check-class
begin
2dup = if 2drop true exit then
@ \ -- target parent \ .class-parent is first field
dup 0= if 2drop false exit then
again ;
: <is-a> ( object 'target -- flag )
swap @ swap >body <<is-a>> ;
: is-a ( object -- flag ) \ stream: target-class-name
' <is-a> ;
: [is-a] ( object -- flag ) \ stream: target-class-name
postpone ['] postpone <is-a> ;
immediate
: <childlike> ( object 'child -- new-object )
>body >r \ -- object \ r: -- child-class
r@ over @ <<is-a>> 0= abort" *** <CHILDLIKE> object's class is not a parent of child-class ***"
r@ class-size realloc \ -- new-object
r> over ! ; \ -- new-object \ class is object's first field
\ <CHILDLIKE> converts an object into a new class, which is a child of its old class.
\ The programmer must still fill in the child fields or otherwise update the object.
\ The new object isn't necessarily going to be at the same address as the old object.
: childlike ( object -- new-object ) \ stream: child-class-name
' <childlike> ;
: [childlike] ( object -- new-object ) \ stream: child-class-name
postpone ['] postpone <childlike> ;
immediate
[toc] | [prev] | [next] | [standalone]
| From | JennyB <jennybrien@googlemail.com> |
|---|---|
| Date | 2016-08-17 05:04 -0700 |
| Message-ID | <bb24efa8-d327-4d9b-b5ef-208b463bafd5@googlegroups.com> |
| In reply to | #50176 |
With any given Forth it should be possible to determine the parent of a word defined using CREATE ... DOES> without needing to add an extra field.
[toc] | [prev] | [next] | [standalone]
| From | hughaguilar96@gmail.com |
|---|---|
| Date | 2016-08-17 10:52 -0700 |
| Message-ID | <0048f867-ef75-4129-aaaa-0f778821f2ed@googlegroups.com> |
| In reply to | #50186 |
On Wednesday, August 17, 2016 at 5:04:44 AM UTC-7, JennyB wrote:
> With any given Forth it should be possible to determine the parent of a word defined using CREATE ... DOES> without needing to add an extra field.
No, this won't tell you if your object type is one of the parents of the class that you are asking about.
class list nada ok-2
w field .fore ok-2
end-class ok
ok
class seq list ok-2
w field .line ok-2
end-class ok
dict-new list ok-1
dup is-a seq . 0 ok-1
dup is-a list . -1 ok-1
drop ok
heap-new seq ok-1
dup is-a seq . -1 ok-1
dup is-a list . -1 ok-1
drop ok
[toc] | [prev] | [next] | [standalone]
| From | hughaguilar96@gmail.com |
|---|---|
| Date | 2016-08-17 19:31 -0700 |
| Message-ID | <c49b2b6e-d767-4c8d-94f4-4fccf247ba13@googlegroups.com> |
| In reply to | #50192 |
On Wednesday, August 17, 2016 at 10:52:17 AM UTC-7, hughag...@gmail.com wrote: > On Wednesday, August 17, 2016 at 5:04:44 AM UTC-7, JennyB wrote: > > With any given Forth it should be possible to determine the parent of a word defined using CREATE ... DOES> without needing to add an extra field. > > No, this won't tell you if your object type is one of the parents of the class that you are asking about. I was confused by what you said. I thought you were referring to the class and questioning why it had to have a pointer to the parent class. Now I realize that you think objects are defined with CREATE DOES> --- they aren't --- the class is defined with CREATE DOES> and the DOES> part makes a new object. The new object is either in the heap or in the dictionary (depending upon whether HEAP-NEW or DICT-NEW were given as a parameter) --- it is anonymous --- you just get an address (to name it, give this address to CONSTANT or to a local variable).
[toc] | [prev] | [next] | [standalone]
| From | anton@mips.complang.tuwien.ac.at (Anton Ertl) |
|---|---|
| Date | 2016-08-18 08:00 +0000 |
| Message-ID | <2016Aug18.100027@mips.complang.tuwien.ac.at> |
| In reply to | #50186 |
JennyB <jennybrien@googlemail.com> writes:
>With any given Forth it should be possible to determine the parent of a word defined using CREATE ... DOES> without needing to add an extra field.
You can only determine which DOES> it is. E.g,:
: foo does> drop ." foo" ;
: flip create foo ;
: flop create foo ;
If you have a word that has the DOES>-action from FOO, you cannot know
if from that if it was defined with FLIP or with FLOP.
- anton
--
M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
New standard: http://www.forth200x.org/forth200x.html
EuroForth 2016: http://www.euroforth.org/ef16/
[toc] | [prev] | [next] | [standalone]
| From | JennyB <jennybrien@googlemail.com> |
|---|---|
| Date | 2016-08-18 21:52 -0700 |
| Message-ID | <d937b88e-91b4-46f9-84ac-3a7ccd051f76@googlegroups.com> |
| In reply to | #50202 |
Of course, and it only works with named words, but it is a pattern I have seen used several times.
[toc] | [prev] | [next] | [standalone]
| From | Julian Fondren <julian.fondren@gmail.com> |
|---|---|
| Date | 2016-08-17 07:11 -0700 |
| Message-ID | <c79b6afa-25b8-41c8-81b9-a5680c0d7041@googlegroups.com> |
| In reply to | #50176 |
On Tuesday, August 16, 2016 at 4:20:10 PM UTC-5, hughag...@gmail.com wrote:
> An argument that can be made against this system is that the first field of every object is now the pointer to the class of that object. The first field is faster than the rest (because the add of a zero offset gets optimized away), but now that is wasted on this pointer that is almost never used. For example, in LIST.4TH I had this:
So use a negative offset for such data.
Bonus advantage: if you get or must maintain structured data for the
outside world, for example a pollfd array for poll(), or a list of
linux_dirent structures from getdents, then you can have a class
mirroring these structures and your offsets will still work. This
need is why you may have seen lots of USINGs in my SWOOP code -- you
can't use late binding in this case because the class information
isn't available.
mini-oof2.fs gained negative offsets, which weren't present in
mini-oof.fs.
Although if you do have the first element at a non-zero offset, as
in objects.fs, you can still get by:
create p1 0 , 1 ,
create p2 333 , 666 ,
42 12 point dict-new constant p3
1 2 colorpoint dict-new constant p4
: example ( -- )
cr ." p1: " p1 cell - [bind] point print
cr ." p2: " p2 cell - [bind] point print
cr ." p3: " p3 print
cr ." p4: " p4 red p4 print
cr ." p4: " p4 green p4 print
cr ." p4: " p4 black p4 print
cr ." p4: " p4 [bind] point print
cr ;
Output:
p1: (0, 1)
p2: (333, 666)
p3: (42, 12)
p4: FF0000 (1, 2)
p4: 00FF00 (1, 2)
p4: 000000 (1, 2)
p4: (1, 2)
-- Julian
[toc] | [prev] | [next] | [standalone]
| From | franck.bensusan@gmail.com |
|---|---|
| Date | 2016-08-17 23:13 -0700 |
| Message-ID | <9dfd5cb4-6975-40cb-ab72-756030623ee1@googlegroups.com> |
| In reply to | #50176 |
Le mardi 16 août 2016 23:20:10 UTC+2, hughag...@gmail.com a écrit : > > An argument that can be made against this system is that the first field of every object is now the pointer to the class of that object. The first field is faster than the rest (because the add of a zero offset gets optimized away), but now that is wasted on this pointer that is almost never used. For example, in LIST.4TH I had this: > > 0 > w field .fore \ .FORE will be fast because it is in the front > constant list > > Now with this new system I would have this: > > class list nada > w field .fore > end-class > > Now the .FORE no longer gets the optimization, although it is the field that really needs to be optimized because HOFs such as EACH etc. all access it inside of a loop. > > > It was trivial to implement --- it took less than one hour to write and it worked the first time --- here it is: > > Anyway, I made another upgrade. I now have a total of two hours invested in this code. These are the features I have now: > 1.) With CLASS and END-CLASS the definition of a class is more readable than the old way in which I just used CONSTANT. > 2.) The IS-A and [IS-A] functions tell you if an object is a member of a particular class or any of its parent classes. > 3.) It is possible to make a new object in either the heap or the dictionary. > To make a new LIST object for the heap use: HEAP-NEW LIST > To make a new LIST object for the dictionary use: DICT-NEW LIST > 4.) The CHILDLIKE and [CHILDLIKE] functions can be used to convert an object from one class into another class assuming that the new class is a child of the original class. This reallocates memory to make the new object big enough. This works for either heap or dictionary objects. > 5.) I have error-checking now. If you try to use a class that isn't actually a class, this gets caught. Also, if you forget END-CLASS and your class is never initialized, this gets caught when you try to use the class. > 6.) NADA will now abort if you try to use it to make an object, which doesn't make any sense. > 7.) I have CLASS-SIZE now that provides the size of an object for that class. I'm not sure what the programmer would want this information for, but it was an easy feature to provide. > > I may yet write that book that Cecil suggested: "ANS-Forth a Guide to Alternate Realities." It could be pretty much based on this code, providing some general-purpose data-structures. This is not the "Forth Way" according to the Forth-200x committee --- so this is an "alternate reality" --- purgatory for Forth programmers who refuse to accept the "Forth Way" and hence can't be considered to be real Forth programmers. > > Anyway, here is the code (note that all of this requires the novice-package): > > > 98769876 constant class-id \ used to make sure a class is actually a class; must be a distinctive value > > 0 > w field .class-parent \ pointer to parent class \ must be first field > w field .class-size \ size of object > w field .class-id \ should always be CLASS-ID > constant class-struct > > \ Every object has a W field in front which is a pointer to the class-struct for its class. > > : check-class ( class -- ) > .class-id @ class-id <> abort" *** tried to use a class that wasn't actually a class ***" ; > > : create-nada ( -- ) \ create a class that has no parent > create > nil , \ .class-parent \ there is no parent > w , \ .class-size \ room for the object's pointer to its class-struct > class-id , \ .class-id \ this is for error-checking > does> ( -- ) > true abort" *** it is illegal to make objects of class NADA ***" ; > > create-nada nada \ NADA is the only class that has no parent > > \ NADA is only available so it can be the parent of classes that have no parent. > \ It is not really a class that can be used as such. > > ' alloc constant heap-new \ give this to the class to get a new object in the heap > ' concrete-alloc constant dict-new \ give this to the class to get a new object in the dictionary > > : class-size ( class -- size ) > .class-size @ > dup 0< abort" *** CLASS-SIZE given a class that never had its .CLASS-SIZE field set by END-CLASS ***" ; > > : object-size ( object -- size ) > @ \ -- class > .class-size @ ; \ -- size > > : class ( -- class offset ) \ stream: class-name parent-name > create here \ -- class > ' >body \ -- class parent > dup check-class \ -- class parent \ make sure PARENT is a class > dup , \ -- class parent \ .class-parent > -1 , \ -- class parent \ .class-size \ this will get filled in by END-CLASS > class-id , \ -- class parent \ .class-id \ this is for error-checking > class-size \ -- class offset > does> ( 'alloc -- adr ) \ make a new object ( 'ALLOC is either HEAP-NEW or DICT-NEW) > >r \ 'alloc -- \ r: -- class > r@ class-size swap execute \ -- object > dup r@ class-size erase \ zero out the object > r> over ! ; \ first field of object is pointer to class > > : end-class ( class offset -- ) > over check-class \ make sure CLASS is a class > swap .class-size ! ; > > : <<is-a>> ( class target -- flag ) > swap \ target class > over check-class over check-class > begin > 2dup = if 2drop true exit then > @ \ -- target parent \ .class-parent is first field > dup 0= if 2drop false exit then > again ; > > : <is-a> ( object 'target -- flag ) > swap @ swap >body <<is-a>> ; > > : is-a ( object -- flag ) \ stream: target-class-name > ' <is-a> ; > > : [is-a] ( object -- flag ) \ stream: target-class-name > postpone ['] postpone <is-a> ; > immediate > > : <childlike> ( object 'child -- new-object ) > >body >r \ -- object \ r: -- child-class > r@ over @ <<is-a>> 0= abort" *** <CHILDLIKE> object's class is not a parent of child-class ***" > r@ class-size realloc \ -- new-object > r> over ! ; \ -- new-object \ class is object's first field > > \ <CHILDLIKE> converts an object into a new class, which is a child of its old class. > \ The programmer must still fill in the child fields or otherwise update the object. > \ The new object isn't necessarily going to be at the same address as the old object. > > : childlike ( object -- new-object ) \ stream: child-class-name > ' <childlike> ; > > : [childlike] ( object -- new-object ) \ stream: child-class-name > postpone ['] postpone <childlike> ; > immediate So now your data is tagged too ? ... For your class-id strange stuff, wouldn't it be better to create a class (MCLASS if CLASS is already used for instance) manually after nada and create other classes using dict-new on MCLASS ? So classes would be objects of class MCLASS. And checking if a parent is a class will be just checking if it is-a MCLASS. btw, what you call is-a is generally called IS-KINDOF (isKindOf in Oforth). is-a generally checks only if the object's class is the same but does not check its parent classes. Franck
[toc] | [prev] | [next] | [standalone]
| From | hughaguilar96@gmail.com |
|---|---|
| Date | 2016-08-18 11:59 -0700 |
| Message-ID | <cf1edd35-b6ba-4ac4-804e-3fb042e61eed@googlegroups.com> |
| In reply to | #50199 |
On Wednesday, August 17, 2016 at 11:13:30 PM UTC-7, franck....@gmail.com wrote: > So now your data is tagged too ? ... Ha! You make it sound as if I've accepted the Devil... Tagged data is only a problem when the operators use the tags. For example, if you have + that works on multiple types (integers, floats, strings, etc.) then the + has to check the tags to determine what it is working with, and usually do a typecast of the data to make them work together. For example, in Racket there is a 3-bit tag meaning that there are 8 possible data types. The + then has to combine the tags into a 6-bit index into a table with 64 versions of itself. By comparison, my pointer on the front is only used IS-A and is not generally used by operators. A lot of people have thought that dynamic-OOP with tagged data was convenient, but then they ran into the serious efficiency problems described above (every time + executes it does a lot of housekeeping before it can finally add two integers together). So, they upgraded their language to have declarations at compile-time that say what type each datum is, so they can compile the correct version of + or whatever without having to do a table lookup at run-time. This clutters up the source-code somewhat. This also doesn't work in Forth (except StrongForth) because there is no way to keep track at compile-time of what type each datum is as it gets bounced around through stack-juggling words. > For your class-id strange stuff, wouldn't it be better to create a > class (MCLASS if CLASS is already used for instance) manually after nada and > create other classes using dict-new on MCLASS ? > So classes would be objects of class MCLASS. > And checking if a parent is a class will be just checking if it is-a MCLASS. I don't get what you are saying here. Maybe you mean that I should have used the name MCLASS rather than NADA for the class which is used as the parent for classes that don't inherit anything (they inherit "nada"). > btw, what you call is-a is generally called IS-KINDOF (isKindOf in Oforth). > > is-a generally checks only if the object's class is the same but > does not check its parent classes. If that is the convention then maybe I will change the names. All in all, I'm not enthusiastic about any of this. I've done without IS-A (or IS-KIND-OF or whatever) for quite awhile.
[toc] | [prev] | [next] | [standalone]
| From | hughaguilar96@gmail.com |
|---|---|
| Date | 2016-08-18 15:11 -0700 |
| Message-ID | <51226078-dad2-4319-a37e-5f5c388aeed7@googlegroups.com> |
| In reply to | #50217 |
On Thursday, August 18, 2016 at 11:59:04 AM UTC-7, hughag...@gmail.com wrote: > On Wednesday, August 17, 2016 at 11:13:30 PM UTC-7, franck....@gmail.com wrote: > > So now your data is tagged too ? ... > > Ha! You make it sound as if I've accepted the Devil... > > Tagged data is only a problem when the operators use the tags. For example, if you have + that works on multiple types (integers, floats, strings, etc.) then the + has to check the tags to determine what it is working with, and usually do a typecast of the data to make them work together. For example, in Racket there is a 3-bit tag meaning that there are 8 possible data types. The + then has to combine the tags into a 6-bit index into a table with 64 versions of itself. By comparison, my pointer on the front is only used IS-A and is not generally used by operators. I said that wrong. Racket has a 2-bit tag, meaning that there are 4 possible data types (integer, string, float or pointer to struct). So the table for every operator is 4-bit with 16 versions of the operator. In Racket, integers are only 30-bit, which is pretty small. Strings, floats and structs are all held in the heap, with a 30-bit pointer to them. Factor has the 3-bit tag with 8 possible data types and 64 combinations of two types of data. Anyway, I have no intention of ever getting involved with any dynamic-OOP language --- except possibly Lua which I think is pretty useful for providing a scripting language on top of a C program --- a scripting language can allow the user to customize a program a lot, and there typically aren't any speed requirements for the scripts. Franck --- is this the way that Oforth works? You have a small tag at the top of every datum?
[toc] | [prev] | [next] | [standalone]
| From | franck.bensusan@gmail.com |
|---|---|
| Date | 2016-08-18 23:14 -0700 |
| Message-ID | <84edde73-1b5d-4fc8-8395-d463d48f1437@googlegroups.com> |
| In reply to | #50222 |
Le vendredi 19 août 2016 00:11:21 UTC+2, hughag...@gmail.com a écrit : > On Thursday, August 18, 2016 at 11:59:04 AM UTC-7, hughag...@gmail.com wrote: > > On Wednesday, August 17, 2016 at 11:13:30 PM UTC-7, franck....@gmail.com wrote: > > > So now your data is tagged too ? ... > > > > Ha! You make it sound as if I've accepted the Devil... > > > > Tagged data is only a problem when the operators use the tags. For example, if you have + that works on multiple types (integers, floats, strings, etc.) then the + has to check the tags to determine what it is working with, and usually do a typecast of the data to make them work together. For example, in Racket there is a 3-bit tag meaning that there are 8 possible data types. The + then has to combine the tags into a 6-bit index into a table with 64 versions of itself. By comparison, my pointer on the front is only used IS-A and is not generally used by operators. > > I said that wrong. Racket has a 2-bit tag, meaning that there are 4 possible data types (integer, string, float or pointer to struct). So the table for every operator is 4-bit with 16 versions of the operator. In Racket, integers are only 30-bit, which is pretty small. Strings, floats and structs are all held in the heap, with a 30-bit pointer to them. > > Factor has the 3-bit tag with 8 possible data types and 64 combinations of two types of data. > > Anyway, I have no intention of ever getting involved with any dynamic-OOP language --- except possibly Lua which I think is pretty useful for providing a scripting language on top of a C program --- a scripting language can allow the user to customize a program a lot, and there typically aren't any speed requirements for the scripts. > > Franck --- is this the way that Oforth works? You have a small tag at the top of every datum? No, Oforth has only 1 bit tag to differenciate integers and pointers to objects. And each object has its first field to (among other things) hold its class, like the field you have added. For MCLASS, Oforth implements classes as objects of class "Class". So to check if an object is a class, you just check if its class is Class. No need to introduce this class-id magic number...
[toc] | [prev] | [next] | [standalone]
| From | hughaguilar96@gmail.com |
|---|---|
| Date | 2016-08-19 01:01 -0700 |
| Message-ID | <810b8836-ef38-45c6-849e-60a281485f3c@googlegroups.com> |
| In reply to | #50234 |
On Thursday, August 18, 2016 at 11:14:17 PM UTC-7, franck....@gmail.com wrote: > Le vendredi 19 août 2016 00:11:21 UTC+2, hughag...@gmail.com a écrit : > > On Thursday, August 18, 2016 at 11:59:04 AM UTC-7, hughag...@gmail.com wrote: > > > On Wednesday, August 17, 2016 at 11:13:30 PM UTC-7, franck....@gmail.com wrote: > > > > So now your data is tagged too ? ... > > > > > > Ha! You make it sound as if I've accepted the Devil... > > > > > > Tagged data is only a problem when the operators use the tags. For example, if you have + that works on multiple types (integers, floats, strings, etc.) then the + has to check the tags to determine what it is working with, and usually do a typecast of the data to make them work together. For example, in Racket there is a 3-bit tag meaning that there are 8 possible data types. The + then has to combine the tags into a 6-bit index into a table with 64 versions of itself. By comparison, my pointer on the front is only used IS-A and is not generally used by operators. > > > > I said that wrong. Racket has a 2-bit tag, meaning that there are 4 possible data types (integer, string, float or pointer to struct). So the table for every operator is 4-bit with 16 versions of the operator. In Racket, integers are only 30-bit, which is pretty small. Strings, floats and structs are all held in the heap, with a 30-bit pointer to them. > > > > Factor has the 3-bit tag with 8 possible data types and 64 combinations of two types of data. > > > > Anyway, I have no intention of ever getting involved with any dynamic-OOP language --- except possibly Lua which I think is pretty useful for providing a scripting language on top of a C program --- a scripting language can allow the user to customize a program a lot, and there typically aren't any speed requirements for the scripts. > > > > Franck --- is this the way that Oforth works? You have a small tag at the top of every datum? > > No, Oforth has only 1 bit tag to differenciate integers and pointers to objects. > > And each object has its first field to (among other things) hold its class, > like the field you have added. > > For MCLASS, Oforth implements classes as objects of class "Class". > So to check if an object is a class, you just check if its class is Class. > No need to introduce this class-id magic number... Well, Oforth is almost a pure OOP system --- your only integrally supported data-type is the integer. There are some downsides to doing this: 1.) Integers are 31-bit rather than 32-bit. 2.) You have extra code going through a pointer to get at your floats; by comparison, VFX has a float-stack which is the x87 float-stack, which is quite efficient. I'm not saying that your Oforth design is necessarily bad. I'm interested in it. In Straight Forth I intend to have only "numbers" without any distinction between integers and floats. I currently have a 64-bit fixed-point number with unity assumed to be 2^32. I could change this so I had a 63-bit fixed-point number with unity assumed to be 2^31 --- this would leave me with one bit for use as a tag like in Oforth. 1.) Pointers would be 32-bit with the other 31 bits ignored. 2.) A fat-xt would consist of a 32-bit cfa and 31-bit pointer to the local-frame. 3.) A string would consist of a 32-bit pointer and a 31-bit size. I could also hae a "number" being an IEEE-754 double-float except that the least-significant bit in the significand would be usurped for use as the tag, slightly reducing the precision. I'm not going to become an Oforth programmer because my primary interest is in supporting Forth cross-compilers, which Oforth doesn't do. I can foresee making Straight Forth similar to Oforth though in regard to the OOP system so that Straight Forth could be used for numerical and text processing programs similar to what Oforth is used for. I don't foresee providing Straight Forth with support for multi-core systems --- that is too difficult (a bit more sophisticated than a blue-collar guy like me wants to delve into), and it puts a straight-jacket on the programs (making data immutable so one process doesn't clobber another process). 1.) Multi-core support is not necessary for the primary purpose of Straight Forth (cross-compilers), and I don't want to add extra complexity that will get in the way of my primary purpose for no benefit. 2.) Multi-core support is not necessary for the secondary purpose of Straight Forth (numeric and text processing) because performance isn't all that crucial. The only program I have in mind is CAM (generating gcode for CNC machines), and this is not time-critical. Even if Oforth given a dual-core system is twice the speed of Straight Forth, nobody will care --- the difference is 1 minute compared to 2 minutes to generate a gcode program --- ease of development of the CAM script is much more important. What do you use Oforth for that is so speed-critical that your multi-core support is necessary?
[toc] | [prev] | [next] | [standalone]
| From | franck.bensusan@gmail.com |
|---|---|
| Date | 2016-08-19 03:14 -0700 |
| Message-ID | <b149c08f-7d72-40d7-ac86-7193eb0d4c7b@googlegroups.com> |
| In reply to | #50238 |
Le vendredi 19 août 2016 10:01:07 UTC+2, hughag...@gmail.com a écrit : > > Well, Oforth is almost a pure OOP system --- your only integrally supported data-type is the integer. > Yes. > There are some downsides to doing this: > 1.) Integers are 31-bit rather than 32-bit. Oforth checks if an integer operation overflows. If so, it switchs to arbitraty precision integers with a pointer on the stack. So, integers have no limit but memory available. For instance : : fact // ( n -- n! ) | i | 1 swap loop: i [ i * ] ; 100 fact . 93326215443944152681699238856266700490715968264381621468592963895217599993 22991560894146397615651828625369792082722375825118521091686400000000000000 0000000000 ok > 2.) You have extra code going through a pointer to get at your floats; by comparison, VFX has a float-stack which is the x87 float-stack, which is quite efficient. Yes, I agree. Oforth is not good with floats. But I didn't found an interesting alternative. That's life... When Oforth will run on 64bits, floats will also be integrally supported. > I'm not saying that your Oforth design is necessarily bad. I'm interested in it. In Straight Forth I intend to have only "numbers" without any distinction between integers and floats. I currently have a 64-bit fixed-point number with unity assumed to be 2^32. I could change this so I had a 63-bit fixed-point number with unity assumed to be 2^31 --- this would leave me with one bit for use as a tag like in Oforth. > 1.) Pointers would be 32-bit with the other 31 bits ignored. > 2.) A fat-xt would consist of a 32-bit cfa and 31-bit pointer to the local-frame. > 3.) A string would consist of a 32-bit pointer and a 31-bit size. > > I could also hae a "number" being an IEEE-754 double-float except that the least-significant bit in the significand would be usurped for use as the tag, slightly reducing the precision. > > I'm not going to become an Oforth programmer because my primary interest is in supporting Forth cross-compilers, which Oforth doesn't do. I can foresee making Straight Forth similar to Oforth though in regard to the OOP system so that Straight Forth could be used for numerical and text processing programs similar to what Oforth is used for. > > I don't foresee providing Straight Forth with support for multi-core systems --- that is too difficult (a bit more sophisticated than a blue-collar guy like me wants to delve into), and it puts a straight-jacket on the programs (making data immutable so one process doesn't clobber another process). > 1.) Multi-core support is not necessary for the primary purpose of Straight Forth (cross-compilers), and I don't want to add extra complexity that will get in the way of my primary purpose for no benefit. > 2.) Multi-core support is not necessary for the secondary purpose of Straight Forth (numeric and text processing) because performance isn't all that crucial. The only program I have in mind is CAM (generating gcode for CNC machines), and this is not time-critical. Even if Oforth given a dual-core system is twice the speed of Straight Forth, nobody will care --- the difference is 1 minute compared to 2 minutes to generate a gcode program --- ease of development of the CAM script is much more important. > > What do you use Oforth for that is so speed-critical that your multi-core support is necessary? It is strange that people think of multi-core support only as allowing speed gain compared to mono-core. This is almost never the case. You will never see a server or a laptop or whatever else at 100% CPU for a long time because of heat, electric consumption and failures. A 100% CPU usage is always a bad sign. But you will see many multi-core support. If you check your laptop, you will see that there are hundred or thousand of thread running (with almost no CPU usage). Let's say your program is an HTTP server and let's say one of your clients is downloading a 1 Go file. What do you do with your other clients ? They will wait for the end of the download because your program uses only one core that is currently busy ? Multi-core support is mainly for parallel execution and high availability, almost never for speed gain compared to mono-core (unless some scientific stuff but those are very particular and rare programms).
[toc] | [prev] | [next] | [standalone]
| From | Ron Aaron <rambamist@gmail.com> |
|---|---|
| Date | 2016-08-19 13:31 +0300 |
| Message-ID | <np6n61$tfe$1@dont-email.me> |
| In reply to | #50244 |
On 19/08/2016 13:14, franck.bensusan@gmail.com wrote: > Oforth checks if an integer operation overflows. If so, it switchs > to arbitraty precision integers with a pointer on the stack. > So, integers have no limit but memory available. 8th has similar semantics. A 'number' is internally one of 'integer', 'float', 'big-integer' or 'big-float' -- but the user of the system usually doesn't need to be concerned with that. Overflow is handled as in Oforth, by changing the internal representation of the number. >> 2.) You have extra code going through a pointer to get at your floats; by comparison, VFX has a float-stack which is the x87 float-stack, which is quite efficient. > > Yes, I agree. Oforth is not good with floats. But I didn't found an > interesting alternative. That's life... > When Oforth will run on 64bits, floats will also be integrally supported. Using the x87 float stack means you have a limited number of floats available on the stack. It's not a good idea for a Forth to so limit the number of floats simultaneously in play, unless the system is very memory-constrained, or unless the intended use is not affected thereby. > It is strange that people think of multi-core support only as > allowing speed gain compared to mono-core. This is almost never the case. Indeed.
[toc] | [prev] | [next] | [standalone]
| From | Raimond Dragomir <raimond.dragomir@gmail.com> |
|---|---|
| Date | 2016-08-19 03:39 -0700 |
| Message-ID | <6a01d1ba-61b8-4e7b-8527-daa8fd35eaf5@googlegroups.com> |
| In reply to | #50244 |
> Let's say your program is an HTTP server and let's say one of your > clients is downloading a 1 Go file. What do you do with your other > clients ? They will wait for the end of the download because your > program uses only one core that is currently busy ? > Since when multi-tasking is possible only with hardware parallelism? > Multi-core support is mainly for parallel execution and high availability, > almost never for speed gain compared to mono-core (unless some scientific > stuff but those are very particular and rare programms). I think multi-core is exactly for that: speed gain compared to single-core. The hardware paralellism is just a mean to achieve speed gain, and it always has been.
[toc] | [prev] | [next] | [standalone]
| From | franck.bensusan@gmail.com |
|---|---|
| Date | 2016-08-19 06:49 -0700 |
| Message-ID | <b3bf61a4-4ebb-4305-8059-ba6f5b5956f1@googlegroups.com> |
| In reply to | #50246 |
Le vendredi 19 août 2016 12:39:59 UTC+2, Raimond Dragomir a écrit : > > Let's say your program is an HTTP server and let's say one of your > > clients is downloading a 1 Go file. What do you do with your other > > clients ? They will wait for the end of the download because your > > program uses only one core that is currently busy ? > > > > Since when multi-tasking is possible only with hardware parallelism? > > > Multi-core support is mainly for parallel execution and high availability, > > almost never for speed gain compared to mono-core (unless some scientific > > stuff but those are very particular and rare programms). > > I think multi-core is exactly for that: speed gain compared to single-core. > The hardware paralellism is just a mean to achieve speed gain, and it always > has been. Well, when I say that Oforth supports "multi-tasking", often answers use multi-core word instead (as here). But yes, I agree with you and even if "multi-core support" was in the question, I should have used "multi-tasking" instead of "multi-core" word. Oforth supports parallel computing by running small tasks concurrently and there can be much more tasks than the number of hardware cores. Even with one core, you can have multiple tasks (but only one will run at a time of course). Those tasks are not used primarily to gain speed. At least, this is not what they are designed for. They are designed to handle lots of requests, dedicating one task per request, for instance. Oforth will automatically resume tasks when the ressource the task is waiting for is available. For instance, even if a task blocks waiting for an answer on a socket, the thread is not blocked and can handle other resumable tasks until the socket answers and makes the task resumable.
[toc] | [prev] | [next] | [standalone]
| From | lawrencedo99@gmail.com |
|---|---|
| Date | 2016-08-19 14:55 -0700 |
| Message-ID | <53168bfe-8dcd-46cb-9fa1-cc369b9b9db9@googlegroups.com> |
| In reply to | #50244 |
On Friday, August 19, 2016 at 10:14:49 PM UTC+12, franck....@gmail.com wrote: > You will never see a server or a laptop or whatever else at 100% > CPU for a long time because of heat, electric consumption and failures. I regularly run one or the other of my desktop machines at close to 100% CPU utilitization for days, even weeks, on end, doing 3D renders. This short sequence <https://vimeo.com/82610823>, for example, is 650 frames, each frame taking about 25 minutes to render. I agree laptops can’t handle this, but desktops and servers can.
[toc] | [prev] | [next] | [standalone]
Page 1 of 3 [1] 2 3 Next page →
Back to top | Article view | comp.lang.forth
csiph-web