1. Structs

I just realised that what I want first is the perfect documentation for structs, perhaps like enum or multiple assignment - anyone care to give it a [quick] stab?
Imagine the compiler has been updated, what would you want/hope/expect the documentation to look like?

Obviously

This forum is perfectly capable of all the formatting(needed), or feel free to use the wiki, it is the content that matters.

I would like to keep this thread tidy: please edit existing posts rather than say one thing on Tuesday and then contradict yourself 7 posts further down on Thursday!

<My attempt will probably go here>

new topic     » topic index » view message » categorize

2. Re: Structs

My idea for struct documentation would be something similar to how structs are used in C. Something like

 
Struct Rect 
  integer x 
  integer y 
  integer w 
  integer h 
End Struct 
 
Rect.x = 10 
Rect.y = 10 
Rect.w = 10 
Rect.h = 10 

Something along those lines.

new topic     » goto parent     » topic index » view message » categorize

3. Re: Structs

Sometimes it might be convenient to "package" several related variables together into another. We call this a "variable structure," or "struct" for short.

You define a structure like this:

struct name 
   string first 
   string middle 
   string last 
end struct 
 
struct address 
   string street 
   string city 
   string state 
   string zip 
end struct 
 
-- structs can hold other structs 
struct employee 
   name name 
   address address 
end struct 

You instantiate a struct like other variable types:

name nName 
address nAddress 
employee nEmployee 

You assign values to a struct like this:

nName.first = "Billy" 
nName.middle = "Gene" 
nName.last = "Smith" 
 
nAddress.street = "1200 Independence Pkwy" 
nAddress.city = "New York City" 
nAddress.state = "New York" 
nAddress.zip = "01234" 
 
nEmployee.name = nName 
nEmployee.address = nAddress 
new topic     » goto parent     » topic index » view message » categorize

4. Re: Structs

well here is my version and sorry i am bad at explaining.

Define some dummy structures for demonstration of my imagination: a structure can contain all primitve datatypes for ex.

struct dummy_struct_t 
   atom a1, 
   sequence s1, 
--  sequence s2, 
   object o1, 
   integer i1, 
   string s1, 
   wstring sw1, 
   $ 

Structure fields may not be initialized within the struct. some structs:

struct dummy_struct_1 
   atom a1, 
   object o1, 
   $ 
 
struct dummy_struct_2 
   atom a2, 
   object o2, 
   integer i2, 
   $ 

define some new structure with a structure variable used in it

struct container_struct 
   atom crap1, 
   sequence scrap1, 
   dummy_struct_1 st1, 
   $ 

now we have a structure that is extended and contains a structure for ex.

struct e_c_s_1 extend dummy_struct_2 
   atom crap1, 
   sequence scrap1, 
   dummy_struct_1 st1, 
   $ 

e_c_s_1 now contains (inherited) the fields of structure dummy_struct_2 and a struct variable dummy_struct_1. This I think could be maybe a future single inheritance thing just like Oberon uses it. Since we are not shooting for classes, forward procedure or function declarations are not allowed in the structure. Oberon would give you the possibility for something like that for ex.

struct xxx_1 extend dummy_struct_2 
   atom x, 
   sequence crap1, 
   struct dummy_struct_1, 
   function average(atom a, atom b),  -- function signature 
   procedure plot(integer x, integer y, integer char=‘*‘), -- procedure signature 
   $ 

declaring and using a structure for ex.

global e_c_s_1 x  
   -- or can use the private attribute or initialized for ex. 
global (private) e_c_s_1 x = {1.0,{5,1.5},{{5.0,"3"}}} 
   -- or  
global (private) e_c_s_1 x = {1.0,{5,1.5}} -- here the dummy_struct_1 part is initializes by the compiler to {} 
   ... 

using struct in procedures or functions

function plot(e_c_s_1 x, integer y, integer char=‘*‘)  
   -- the default value for e_c_s_1 x could be {} or some other legal initializer s. obove,  
   -- or initializers are forbidden in signatures 
 
   container_struct y = {0.1, {}, {1.5,"x"}} 
     or 
   container_struct y 
   y.crap1=0.1 
   y.scrap1={{},5,1.5} 
   y.st1.a1=0.1 
   y.st1.o1="ddddd" 
 
   position(x.y, y.crap1) 
   puts(1, char) 
   return {y.crap1, y.st1, y} 
end function 

i guess i get slapped now.

new topic     » goto parent     » topic index » view message » categorize

5. Re: Structs

Since a lot of Eu programming involves interfacing with .dlls and .so libraries, it seems to me that structs should be able to declare C types as well as Euphoria types.

That would do away with all the allocating, poking and peeking difficulties.

new topic     » goto parent     » topic index » view message » categorize

6. Re: Structs

yep, that would be neat, but then we should have unions too. but phix has that in cffi already.

new topic     » goto parent     » topic index » view message » categorize

7. Re: Structs

after some discussions with my two other people we came to the conclusion, that the following should be possible in my example:

struct dummy_struct_t  
   atom a1,  
   sequence s1,  
--  sequence s2,  
   object o1,  
   integer i1,  
   string s1,  
   wstring sw1,  
end struct 

the extension was something they liked for 2 reasons:

1.) you can keep your general structures in a module and specialize them

and

2.) even so not envisioned, the possibility of inheritance.

Richard

new topic     » goto parent     » topic index » view message » categorize

8. Re: Structs

It is gentler to extend ideas that we already have (less learning, simpler) then to invent a complete new "struct" syntax.

simplest case

A "struct" is a kind of "enum".

struct point X, Y, $ 

What you get is local enums `X` and `Y` for exclusive use in dot notation

point mydot 
mydot.X = 3 
mydot.Y = 5 
 
? mydot 
    --> {3,5} 

Simple and convenient. The sequence `mydot` is free to have any data-values and any kind of changes. The names `X` and `Y` can be freely used in alternative local scopes. Classic Euphoria freedom.


adapt existing user `type`

A "struct" is a special case of user "type".

An extension of the existing `user data-type`. Use it with or without type-checking. This adds the convenience of dot-notation.

type point( object x ) 
 
    struct 
        integer X, 
        atom Y, 
        string s, 
        $ 
 
    return true 
end type 
 
point mydot 
 
mydot.X = 4 
mydot.Y = 8 
mydot.s = "blue" 
 
? mydot 
--> { 4, 8, "blue" } 
 
? point( {2,3} ) 
--> false 

This way both kinds of "struct" could co-exist. The simple form could be used most of the time in general programming. The user-type version when you need rigor.

_tom

new topic     » goto parent     » topic index » view message » categorize

9. Re: Structs

_tom said...

The simple form could be used most of the time in general programming. The user-type version when you need rigor.

The only reason I'd go with a more complicated spec with a block definition is so structs can eventually have private/public variables and, eventually, methods. smile

new topic     » goto parent     » topic index » view message » categorize

10. Re: Structs

euphoric said...

The only reason I'd go with a more complicated spec with a block definition is so structs can eventually have private/public variables and, eventually, methods. smile

You invent OOP smile

Current Phix dot notation is an option that you get when compiling Phix into an executable. That means is is a low cost option that can be ignored (via a simple switch) when creating Phix. Inventing OOP will take major design thinking.

_tom

new topic     » goto parent     » topic index » view message » categorize

11. Re: Structs

I don't think adding to OOP to Euphoria would be a good idea. The idea of Euphoria is to be simple. I know structs are kinda like a low-key OOP, but they're still pretty easy to understand. Like my idea of structs (I did post about this earlier, but restating my position on keeping structs simple)

struct player 
  integer health 
  atom x_pos,y_pos 
  string name 
end struct 
 
player.health = 100 
player.x_pos = 15 
player.y_pos = 15 
player.name = "bob" 

That would be my idea for structs, I think a couple other users had similar idea to mine.

new topic     » goto parent     » topic index » view message » categorize

12. Re: Structs

_tom said...
euphoric said...

The only reason I'd go with a more complicated spec with a block definition is so structs can eventually have private/public variables and, eventually, methods. smile

You invent OOP smile

Almost, but that's not the intent.

new topic     » goto parent     » topic index » view message » categorize

13. Re: Structs

structs that mirror the style used by 'c' makes a lot of sense; this enables easier .so interfacing -- no argument here

what is needed is a complementary "generic" form

  • no need for each item to have a fixed data-type
  • just names for index values so existing Phix dot-notation is nicer to use
  • ability to extend to nested sequences
  • building new forms by composition

_tom

new topic     » goto parent     » topic index » view message » categorize

14. Re: Structs

data-types

A data-type "limits the values permitted for an object."

Everything is an object; an object is the unlimited data-type.

Two fundamental objects: atom, sequence

Variations on the two fundamentals:

     
atom --> integer 
sequence --> string , struct 
     
type --> user defined data-type 

Question? Interfacing with 'c'; can special data-types be invented to make interfacing with an .so easier?


A struct is "a sequence; each item has a data-type; each item has a named index; default values may be assigned to an item."

struct zoo 
    string name = "" 
    integer legs = 0 
    atom  height = 0 
    atom speed = 0 
end struct 

This syntax creates a zoo struct identifier, a zoo() function for testing, and a zoo_new() function for initialization, and local enums (name,legs,height,speed) that can be used with dot-notation.

  • The struct name zoo is used to declare an new instance of the zoo struct-sequence.
zoo critter 
  • The zoo_new() function assigns default values
critter = zoo_new() 
? critter 
--> { "", 0, 0, 0 } 
 
 
zoo fauna = zoo_new( name := "osterich" ) 
? fauna 
--> { "osterich", 0, 0, 0 } 
  • The zoo() function tests if an object belongs to a struct.
? zoo( critter ) 
--> true 
 
? zoo( 3.14 ) 
--> false 
  • You can subscript struct items
critter[1] = "emu: 
critter[2] = 2 
critter[3] = 1.9 
critter[4] = 50 
  • you can use dot-notation with struct items
critter.name = "emu" 
critter.legs = 2 
critter.height = 1.9 
critter.speed = 50 
 
 
? critter 
--> { "emu", 2, 1.9, 50 } 

_tom

new topic     » goto parent     » topic index » view message » categorize

15. Re: Structs

Things like this are often necessary and useful. So the dot notation shouldn't really stop at a single level:

point = {integer x, integer y)

critter.position = point

critter.position.x = 10 critter.position.y = 20

critter.position = {20,20}

critter.position += {50,40}

critter.path = repeat(critter.position,10) i.e. an array in which you could store the last 10 locations

new topic     » goto parent     » topic index » view message » categorize

16. Re: Structs

irv said...

Things like this are often necessary and useful. So the dot notation shouldn't really stop at a single level:

You can do this today using Phix

enum X,Y 
 
sequence point = {0,0} 
 
point.X = 10 
point.Y = 20 
 
sequence position = {} 
position &= point 
? position 
--> {10,20} 
 
position = repeat( point, 4 ) 
? position 
 
position.2.X = 3 
position.2.Y = 5 
 
? position 
--> {{10,20},{10,20},{10,20},{10,20}} 
 
--> {{10,20},{3,5},{10,20},{10,20}} 
 
 
for i=1 to 4 do 
    position.i.Y = i 
end for 
? position 
--> {{10,1},{3,2},{10,3},{10,4}} 

_tom

new topic     » goto parent     » topic index » view message » categorize

17. Re: Structs

euphoric said...
_tom said...
euphoric said...

The only reason I'd go with a more complicated spec with a block definition is so structs can eventually have private/public variables and, eventually, methods. smile

You invent OOP smile

Almost, but that's not the intent.

Oh yes it is. smile

Some brief thoughts about object orientation:

  • It is a perfectly valid programming paradigm, sometimes.
  • Other perfectly valid programming paradigms do exist.[1]
  • Problems arise when shoe-horning (parts of) a solution into an inappropriate programming paradigm.[1]
  • The best solution is probably quite often a mixture of different programming paradigms.[2]
  • Fundamental radicalism is almost as bad in programming as it is in politics and religion.[2]
  • Trivial components in no way guarantee that the larger system is automatically bug free.[3]
  • Thousands of trivial components do not make complicated problems any easier to find.[3]
  • Making something harder to debug does not help anyone, ever.
  • Forcing someone to use something they hate or do not understand does not usually help much either.
  • Allowing someone else to do things in their own (peculiar) way is just plain old fashioned common decency.

Footnotes: Repeat firmly and calmly [1]yes they do [2]yes it is [3]no they do not. Resist temptation to shout.

Anyway, enough of that. If we can sneak in a few little extras in a way everyone is comfortable with, we should.

Whether you love or hate oop, I think we can all agree we all want something like this:

Suppose you have say struct rectangle, struct square, struct circle, and struct triangle.
Do you want to be able to pass any of those to a generic routine that accepts a struct shape?
If so, how do we define struct shape, and something else, say struct address, that naturally cannot be(/type checks if) passed into a struct shape parameter?
How do we best express that sort of relationship in a simple, natural and intuitive way?

PS Let's just all agree not to even consider multiple inheritance!

new topic     » goto parent     » topic index » view message » categorize

18. Re: Structs

wow Pete this great i like to suggest some things, that, i am sure i will to have to edit. but here it goes:

-- The object-oriented features of PHIX all come from classes. The class hierarchy has as its root the class Object.  
-- Object defines a minimum level of functionality that each derived class has, and a default implementation for that functionality. 
-- Classes are programmer defined types. Support for classes are what makes PHIX an object oriented language, giving it encapsulation,  
--   inheritance, and polymorphism. PHIX classes support the single inheritance paradigm, extended by adding support for abstract classes.  
-- A class can be exported, which means its name and all its non-private members (those that are not decorated with public) are exposed  
--   externally to the DLL or EXE 
-- All member functions of 'synchronized' (decorator for a class) classes are synchronized for threads.  
-- Classes can not be nested 
 
-- optinal '(' with 'T' list for generics ')', when brackets are used, atleast one 'T' has to be in the list 
-- if a class is decorated with [public] it is visible outside the definition file 
-- if a class is decorated with [abstract] class 
	-- Class methods are defined exactly like a normal procedure or function procedure. 
	-- Abstract procedures/functions can be declared within an abstract class. Abstract procedures are not implemented within a class. 
	-- They are simply placeholders defining how a given method is implemented in classes which inherit an abstract class. 
-- optinal '(' with 'T' list for generics ')', when brackets are used, atleast one 'T' has to be in the list 
-- Base class construction is done by calling the base class constructor by the name 'super' 
 
-- ALL CLASSES METHODS ARE VIRTUAL 
-- [abstract | override] Procedure/function header 
-- Class methods are defined exactly like a normal procedure or function procedure. Abstract procedures can be declared within an abstract class.  
-- Abstract procedures are not implemented within a class. They are simply placeholders defining how a given method is implemented in classes which  
--  inherit an abstract class. 
-- To override a class method defined in an inherited class you prefix the method definition with the OVERRIDE keyword. Overridden methods preserve the  
--  interface but replace the implementation. Method calls will always refer to the method implementation according to the dynamic type of a object. 
-- By overriding a method no new component is established. The existing method is replaced with the overridden method. 
-- Methods that are decorated with 'final' can not be overriden. 
 
 
 
class point 
  atom x, y, w, h      -- initialized with NAN 
  string description   -- initialized with "" 
  public dummyint = 1  -- if = 1 is omitted, it should also be initialzed, maybe to the larges neg. INT possible 
  public sequ = {4, 5, 6}  -- or default initialized with {} 
 
  point() -- initializer, does nothing 
  end point 
 
  point(atom x, atom y, atom w, atom h) -- initializer overloaded 
    .x = x .y = y .w = w .h = h     -------  the period '.' is short for this 
  end point 
 
  point(atom x, atom y, string description) -- initializer overloaded 
    .x = x .y = y .description = description 
  end point 
 
  public procedure description(string descript) 
    .description = descript 
  end description 
 
  public function description() 
    return .description 
  end function 
 
  public procedure setxy(atom x, atom y) 
    .x = x .y = y 
  end description 
 
  public procedure getx() 
    return .x 
  end description 
 
  public procedure getMultiplierSequence() 
    return .sequ 
  end description 
 
end class 
 
-- make a new class - maybe there should be a new keyword 'class', but object should be able to be synonym 
object p1 = new(point())  -- or 
object p2 = new(point(1,2,3,4))  -- or 
object p3 = new(point(1,2,"some text")) 
 
-- make a new sequence of classes 
sequence s1 = new(point(1,2,"some text"), 100) 
 
-- copy a sequence of classes. s2 contains a distinct new deep copy of s1, therefore s2[1] != s1[1], but with same data content 
sequence s2 = s1 
sequence s2[2] = {}  -- s2[2] is empty, s1[2] is not 
 
bool test = ISMEMBER(s2[2], point) -- returns true 
 
 
-- destroy a/the class/es 
destroy(p2) 
p3 = {} 
s1 = {} 
 
-- use 
p3.x = 0.01 -- error variable not public, must be set by setxy(atom x, atom y) or some other defined method 
p3.dummyint = 1 -- correct is public 
integer testint = p3.dummyint -- correct is public 
sequence w = sq_mul(5, p3.sequ)  -- w is {20, 25, 30} (out of phix help) 
--or 
w = sq_mul(5, p3.getMultiplierSequence()) 
 
--sequence use 
s1[50].setxy(0.1, 0.2) 
 
 
 
-- inherit class point 
class circle extend point  -- single inheritance, the compiler check for circulars an pukes if necessary. 
  atom radius 
  super(1,2,3,4) 
end class 
 
 
 
 
 
-- abstract classes describe a list of functions that a class that inherits from the abstract class must implement.  
--   A class that implements an abstract class can be converted to a reference to that abstract class. 
abstract class phix1 
 
    procedure foo() 
    function bar(integer x) 
 
    final procedure finalproc(integer x) -- this procedure or function may not be implemented in a class 
       ... 
    end procedure 
 
end class 
 
-- An instance of an abstract class cannot be created. 
 
class phixC extend point implements phix1 -- ,phix2, .. 
 
    function bar(integer x) -- ok 
      ... 
    end procedure 
 
    procedure foo() -- ok 
      ... 
    end procedure 
 
    procedure finalproc() -- error, cannot override final finalproc 
      ... 
    end procedure 
 
end class 

new topic     » goto parent     » topic index » view message » categorize

19. Re: Structs

petelomax said...
euphoric said...
_tom said...

You invent OOP smile

Almost, but that's not the intent.

Oh yes it is. smile

No. All I really want is encapsulation, which is part of OOP, but is not OOP.

We can already encapsulate code in modules (include files). This would just be a different form of that, with maybe better protection or ease-of-use.

I haven't thought too hard about it, so I don't have a list of pros/cons just yet.

new topic     » goto parent     » topic index » view message » categorize

20. Re: Structs

here is a little language, that is interesting for some ideas. they use struct in an oberon way, but took out a lot of the oo possibilities.

https://vlang.io/docs

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu