Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.forth > #50166 > unrolled thread

the IS-A function

Started byhughaguilar96@gmail.com
First post2016-08-15 23:10 -0700
Last post2016-08-18 18:31 -0700
Articles 20 on this page of 45 — 12 participants

Back to article view | Back to comp.lang.forth


Contents

  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 →


#50166 — the IS-A function

Fromhughaguilar96@gmail.com
Date2016-08-15 23:10 -0700
Subjectthe 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]


#50167

Fromhughaguilar96@gmail.com
Date2016-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]


#50175

Fromhughaguilar96@gmail.com
Date2016-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]


#50176

Fromhughaguilar96@gmail.com
Date2016-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]


#50186

FromJennyB <jennybrien@googlemail.com>
Date2016-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]


#50192

Fromhughaguilar96@gmail.com
Date2016-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]


#50195

Fromhughaguilar96@gmail.com
Date2016-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]


#50202

Fromanton@mips.complang.tuwien.ac.at (Anton Ertl)
Date2016-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]


#50233

FromJennyB <jennybrien@googlemail.com>
Date2016-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]


#50188

FromJulian Fondren <julian.fondren@gmail.com>
Date2016-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]


#50199

Fromfranck.bensusan@gmail.com
Date2016-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]


#50217

Fromhughaguilar96@gmail.com
Date2016-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]


#50222

Fromhughaguilar96@gmail.com
Date2016-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]


#50234

Fromfranck.bensusan@gmail.com
Date2016-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]


#50238

Fromhughaguilar96@gmail.com
Date2016-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]


#50244

Fromfranck.bensusan@gmail.com
Date2016-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]


#50245

FromRon Aaron <rambamist@gmail.com>
Date2016-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]


#50246

FromRaimond Dragomir <raimond.dragomir@gmail.com>
Date2016-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]


#50250

Fromfranck.bensusan@gmail.com
Date2016-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]


#50258

Fromlawrencedo99@gmail.com
Date2016-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