1. fake class in OE

Just brainstorming here, because it's gnawing at me...

A fakeclass.cow.e , wherein there's global functions setclass() and getclass() (and maybe some other stuff), called like

Success = setclass("cow1","color","brown") 

such that "cow1" is an enumerated item in list1 , "color" is the same enumeration in a list2 , "brown" is in another list. List contents can be out of order, as long as they stay synchronized. You cannot set parameters on cows flying, because flying is not in list2. You can search for brown cows by looking at the color list. You can set cow12 walked a mile today (based on GPS, to correlate to milk production), but the embedded function of walking() (found in list2) is going to see if the where and how fast is within parameters before accepting it.

ListOfParameters = getclass("cow","walking") 

The goal of this was only to re-use the "object" cow.e for all cows, and make code run that's exclusive to and shared with all cows. It can be copied over and used for goats too. The lists can be saved to hdd between runs. I think it meets the definition of class, even though it doesn't use the designed syntax of other languages.

Kat

new topic     » topic index » view message » categorize

2. Re: fake class in OE

katsmeow said...

Just brainstorming here, because it's gnawing at me...

A fakeclass.cow.e , wherein there's global functions setclass() and getclass() (and maybe some other stuff), called like

Success = setclass("cow1","color","brown") 

such that "cow1" is an enumerated item in list1 , "color" is the same enumeration in a list2 , "brown" is in another list. List contents can be out of order, as long as they stay synchronized. You cannot set parameters on cows flying, because flying is not in list2. You can search for brown cows by looking at the color list. You can set cow12 walked a mile today (based on GPS, to correlate to milk production), but the embedded function of walking() (found in list2) is going to see if the where and how fast is within parameters before accepting it.

ListOfParameters = getclass("cow","walking") 

The goal of this was only to re-use the "object" cow.e for all cows, and make code run that's exclusive to and shared with all cows. It can be copied over and used for goats too. The lists can be saved to hdd between runs. I think it meets the definition of class, even though it doesn't use the designed syntax of other languages.

Kat

I like this idea. Perhaps once struct supported is added, this can be added next. Or a feature to be added in the future?

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

3. Re: fake class in OE

Hi

I don't know, this doesn't look like it's making things simpler or easier to use, and definately looks more pythonesque. Of course I wouldn't have to use if I didn't want to, but would it pass the readable code by someone else in 10 years test?

Cheers

Chris

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

4. Class/Interface/Contract -- Re: fake class in OE

Some thougths from me ...
I hope my english is ok.


--[ <built-in> 
--[+ About An Interface 
---   
--+] 
interface Class 
  --[ About A Contract 
  -- a "contract name" is optional, 
  -- it is not to be the same name as the routine or variable. 
  -- could be used for error reporting. 
  -- If a contract is not satisfied an error will occur (aka ##error:crash()##) 
  -- example: (# is like : for namespace. I choose that to differ from namespaces -- i.e. instead of ::) 
  --   sequence message = {Class#contract[_NAME_], Class#contract[_REQUIREMENTS_]} 
  --   crash_message("Contract %s not satisfied!\nRequirements: %s", message) 
  --] 
   
  contract create 
    atom class_pointer: -1 <= return >= 0 
    export procedure create() return class_pointer 
    docline "-1 means error, >= 0 means 'This is my pointer and I love you so much!'" 
  end contract 
   
   
  --[ About @ 
  --- @ could be a routine name and will be (auto-) called if its Requirements are not satisfied 
  --- I think for ClassError it must be a procedure. 
  --- And the format (fmt) of ##error:crash_message(sequence fmt)## is optional to use 
  --- example: 
  ---   fmt could be by default: sprintf("%s is neither %d nor %d", {...}) 
  ---   fmt by user would be used like any ##sprintf##  i.e. @ClassError("...", {...}) 
  --- See: [["About A Contract"]] 
  --] 
 
  contract destroy 
    integer code return >= 1  @ClassError -- should it be @ClassError() ?? 
            or   return <= 0  @ClassError --- 
    export function destroy() return code 
    docline "<= 0 means no error and >= 1 means an error" 
  end contract 
   
  --- More (explicit) contracts if needed ... 
   
  --[ About 'magic routines' 
  --  It's magic if no function was defined 
  --  Like in other languages (Java, etc.) 
  --] 
   
  export function equal() return boolean 
  export function hash()  return sequence 
   
  export function serialize() return sequence 
  export procedure deserialize() 
  [...] 
end interface 
--] 
 
interface Animal: Class -- ": Class" is optional, any class/interface/contract/etc. will be inherited from Class 
  contract name 
    sequence name = "Animal" 
  end contract 
   
  -- Return name of Animal 
  contract 
    export function get_name(): string 
    return name: sequence 
  end contract 
   
  --- override in an interface is a 'silent' contract: this must be overridden! 
  override function equal() -- should a type-hint be required ?? 
  override function hash()  ---  
end interface 
 
class Cow: Animal 
  sequence name = "Cow" 
 
  export function get_name(): string 
    return name 
  end function 
 
  export function equal(@Class seq) 
     return equal(seq#name, name) 
  end function 
 
  export function hash() 
    return name 
  end function 
end class 
 
class Goat: Cow 
  override sequence name = "Goat" 
  [...] 
end class 

Use (strict)

Goat#get_name() 

Use (compat)

class_pointer goat_     = getclass("Goat") -- or get_class("Goat")  -- is case-insensitive 
method_return goat_name = getmethod(goat_, "get_name", {})          -- same here 


class_pointer is an atom
method_return is a sequence; {atom class_pointer, sequence method_name, object return_value}

But I prefer

class_pointer goat_ = class:new("Goat") 
method_return goat_name = class:method(goat_, "get_name", {}) 
-- or class:call(...) 
-- or class:func(..) / class:proc(...) 

I know this is a big thing to implement.
It could be implemented step by step.

The point is to use interfaces and contracts.
Better documentation to read by an IDE/Editor and any human.

The first step could be to ignore 'interface ... end interface'.
It's than a stub. Used for documentation, only.

--[ About "doc...end doc" and "docline" 
--- I think it's good practice to say which comment is more than a hint for the code owner. 
--] 


Forked into: [OE] Suggestion for OpenEuphoria 'Next' | Class/Interface/Contract

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

5. Class/Interface/Contract -- Re: fake class in OE

mitgedanken said...

But I prefer

class_pointer goat_ = class:new("Goat") 
method_return goat_name = class:method(goat_, "get_name", {}) 
-- or class:call(...) 
-- or class:func(..) / class:proc(...) 

Erm, this currently/already works in Phix

class Goat 
    string name 
    function get_name() 
        return name 
    end function 
end class 
 
Goat goat = new({"Gertrude"}) 
?goat.get_name() 

Note that goat.name works the same as goat.get_name() here, because it recognises the "get_" part.

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

6. Class/Interface/Contract -- Re: fake class in OE

To expand on that (Pete will correct me if I'm wrong):

With Phix, a class can have public, or private, properties.

When you declare a property as public, it acts just like any other variable, except that it is "owned" by the class instance. Types work the same as they do elsewhere, but with an added feature (we get to that later).

class Cow 
  public integer horns; 
end class 
 
Cow bossie = new() ? bossie -- {"struct","Cow",4,1} instance 1 of class Cow 
Cow bessie = new() ? bessie -- {"struct","Cow",4,2} instance 2 of class Cow 
 
bessie.horns = 2 
bossie.horns = 0 
? bessie.horns -- prints 2 

If you declare a property as private, Phix looks for a routine of the same name, prepended by "set_" or "get_".

class Cow 
  private integer horns; 
   
  procedure set_horns(integer n)  
  -- we have a chance to do something in addition to just setting the number of horns 
  if n < 0 or n > 2 then ?"You're kidding, right?" -- made up example; 
  else this.horns = n end if 
  end procedure 
  
  function get_horns() 
   -- maybe do something here (beep once for each horn?) 
  return this.horns 
  end function 
 
end class 
 
? bossie.horns -- automatically calls function get_horns() for the bossie instance 
bessie.horns = 3 -- automatically calls procedure set_horns() for the bessie instance 

Properties aren't limited to the normal types (integer, bool, atom, string, sequence, or user-written types), they can also be declared as being a class type. For example, think of a Dialog window, which pops up a message.

It will have, at the least, a label with some text, a button or two, and perhaps an Icon: So you will have written a Button class, an Image class, and a Label class. Then the Dialog might have either public or private properties of those types:

 
include Image.e -- exports declaration and code for class Image; 
 
class Dialog  
  private Image icon; 
 
  procedure set_icon(Image i)  -- will only accept an instance of Image class; 
    ? i -- {"struct","Image",6,1} <-- this is the instance passed to set_icon() 
    -- do something with that image (resize it, perhaps?) 
    this.icon = i 
    -- then update the dialog's icon, probably by calling a c_proc() In GTK, it would look something like: 
    c_proc(define_c_proc(GTK,"gtk_dialog_set_image",{C_POINTER,C_POINTER}),{this.handle,i.handle}) 
  end procedure 
 
end class 
 
Dialog d = new() 
Image x = new({"mongoose.jpg"}) 
d.icon = x -- calls the set_icon() function for class Dialog ,instance d, passing the Image structure; 

Of course, a Dialog is a kind of Window, so they share some of the same properties, for example, size. Rather than write and debug a set_size() function for every object that has a size property, it's better to do that just once:

include Window.e -- exports declaration and code for class Window  
     -- the Window class declares a private sequence size; 
include Image.e  
 
class Dialog extends Window -- inherit properties and code from Window (can inherit from more than one class) 
  private Image icon; 
 
  procedure set_icon(Image i)  
    this.icon = i 
    -- update the dialog's icon 
  end procedure 
 
end class 
 
Dialog d = new() 
d.size = {300,400} -- calls the set_size() function in the Window class 
 
Image x = new({"mongoose.jpg"}) 
d.icon = x 

Now, anything that derives from a Window automatically has the ability to set or get its size.

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

7. Alternative: Module -- Re: fake class in OE

[Draft for Euphoria]

An alternative to "class ..."

An explicit defined module must be instanciated to be accessible.
Not like a file with/without a namespace.


For short

  1. a module is like a namespace and like a routine
    1. but module must be instanciated
    2. and needs a procedure "new"
    3. "Module#routine(..)" and "Module#var" if it's export/public or have a "get_var" or "set_var" (both or one of them)
  2. only anything above "module" will be usable if only namespace is used


namespace module_animal -- still optional 
 
-- "export module" is equal to "export function/procedure" 
export module Animal is Class  -- or as above, but I think, that's better then Animal : Class (it seems like a namespace) 
-- a module does NOT inheritance from Class automaticly! 
-- Class is more like a struct/type 
 
-- anything like above 

Use as above ...
but include loads ONLY anything above module definition

-- "public module" is equal to "public function/procedure" 
public module Cow is Animal 
use mymods/Animal.em -- .em Euphoria Module -- a Module could be self executable but I think it must not. 
-- 'use' could be before 'module'  
-- [...] 


The Horns Example (simple)

namespace module_cow 
 
public module Cow is Animal 
use mymods/Animal.em 
 
integer horns 
sequence name 
 
-- procedure new() is required for any module! 
export procedure new(sequence name, integer horns = 2) 
  #name = name 
  #horns = horns 
export procedure 
 
export procedure rename(sequence name) 
  #name = name 
end procedure 
 
export function get_horns() 
  return horns 
end function 
 
export procedure set_horns(integer amount) 
  horns = amount 
end procedure 
use mymods/Cow.em 
 
my_cow = Cow() 
? my_cow#name  -- "Luisa" 
? my_cow#horns -- 2 
 
your_cow = Cow("Priceless", 3) 
? your_cow#name  -- "Priceless" 
? your_cow#horns -- 3 
 
your_cow#horns = 0 
your_cow#rename("Princess") 
? your_cow#horns -- 0 
? your:cow#name  -- "Princess" 
? equal(my_cow, your_cow) -- 0; same as irv's class example 


Forked into: [OE] Suggestion for OpenEuphoria 'Next' | Module

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

8. Alternative: Module -- Re: fake class in OE

Responding to mitgedanken ...

The problem with export function get_horns() is the same problem with most computer languages, and some people: it's fixed, the system is fixed, you cannot add a get_ anything else while the program is running, or any sort of parameter which you may discover next week. With this way of doing things, the programmer must know in advance all the possible things that could be setted or getted, and write code for it, which if you think about all the things in the world you know parameters about, is going to make for a terribly bloated application.

Responding to Icy_Viking ...

I hoped i was saying this could be written in OE and added soon as you are done, because i suggested it as an include file. There's no developers working on OE, there won't be any new releases (hasn't "release often" turned into 10 years now?). Phix seems to have a class that's as good as any language's. As i cannot write a real class for OE, i thought of a fake class. A beauty of it being OE source code is you can tweak it to suit your needs. For instance, use an external database for the parameters of each item and class, such as SQL?

Kat

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

9. Re: Responding to mitgedanken -- Re: fake class in OE

katsmeow said...

Responding to mitgedanken ...

The problem with export function get_horns() is the same problem with most computer languages, and some people: it's fixed, the system is fixed, you cannot add a get_ anything else while the program is running, or any sort of parameter which you may discover next week. With this way of doing things, the programmer must know in advance all the possible things that could be setted or getted, and write code for it, which if you think about all the things in the world you know parameters about, is going to make for a terribly bloated application.

[...]

Kat

You're right!
I tried to use only current Euphoria keywords as possible.

Something like ... ?

writable integer horns  -- if it's writable it's readable too 
readonly sequence name 

Or mutable immutable. Both examples only as a suggestion.

Edit

public integer horns 
export sequence name 

But I'm not sure if this is a good idea.

end Edit


  my_cow#name = "Polly" -- error/crash 
  my_cow = Cow#name -- ok 
  my_cow = Cow#get_var('name') -- ok 
  -- set_var(..., ...) -- error/crash 
   
  my_cow#horns = 1 -- ok 
  my_cow#set_var('horns', 1) -- ok 
  if my_cow#horns > 0 then -- ok 
   ... 
  end if 

Sara |mitgedanken|

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

10. Alternative: Module -- Re: fake class in OE

katsmeow said...

Responding to mitgedanken ...

The problem with export function get_horns() is the same problem with most computer languages, and some people: it's fixed, the system is fixed, you cannot add a get_ anything else while the program is running, or any sort of parameter which you may discover next week. With this way of doing things, the programmer must know in advance all the possible things that could be setted or getted, and write code for it, which if you think about all the things in the world you know parameters about, is going to make for a terribly bloated application.

Responding to Icy_Viking ...

I hoped i was saying this could be written in OE and added soon as you are done, because i suggested it as an include file. There's no developers working on OE, there won't be any new releases (hasn't "release often" turned into 10 years now?). Phix seems to have a class that's as good as any language's. As i cannot write a real class for OE, i thought of a fake class. A beauty of it being OE source code is you can tweak it to suit your needs. For instance, use an external database for the parameters of each item and class, such as SQL?

Kat

Well yes a fake class is a good idea. True Phix does have a struct/class support. Also, yeah its been years since OE has had an official release.

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

11. Alternative: Module -- Re: fake class in OE

katsmeow said...

Responding to mitgedanken ...

The problem with export function get_horns() is the same problem with most computer languages, and some people: it's fixed, the system is fixed, you cannot add a get_ anything else while the program is running, or any sort of parameter which you may discover next week. With this way of doing things, the programmer must know in advance all the possible things that could be setted or getted, and write code for it, which if you think about all the things in the world you know parameters about, is going to make for a terribly bloated application.

... Kat

That's correct. There may be a way to avoid that problem, however,if the base class has 3 routines: add_property(), set_property(), and get_property(), along with a dictionary or db to store the name/value pairs (and perhaps a function to be called to override the one declared in the base class?).

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

12. Re: fake class in OE

Only a hint

Namespaces can be used in routine_id()
But for now there is no way to get the namespace programmatically.
A constant must be set instead.

Sara |mitgedanken|

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

13. Alternative: Module -- Re: fake class in OE

irv said...
katsmeow said...

Responding to mitgedanken ...

The problem with export function get_horns() is the same problem with most computer languages, and some people: it's fixed, the system is fixed, you cannot add a get_ anything else while the program is running, or any sort of parameter which you may discover next week. With this way of doing things, the programmer must know in advance all the possible things that could be setted or getted, and write code for it, which if you think about all the things in the world you know parameters about, is going to make for a terribly bloated application.

... Kat

That's correct. There may be a way to avoid that problem, however,if the base class has 3 routines: add_property(), set_property(), and get_property(), along with a dictionary or db to store the name/value pairs (and perhaps a function to be called to override the one declared in the base class?).

I had imagined add_ would be part of set_, but yes, having them be separate makes it easier to apply different rules and error checking to each. It's also more possible (as in, without breaking anything) for a new feature that cannot be properly described yet. You must be thinking of the platypus problem?

There's other database management tasks unrelated to the class which would need tending to. I had imagined a OE layer to deal with the class work, and interface to your choice of database behind, because once the db is working, it becomes just a "black box" you no longer think about. Simple small stuff may be dealing with only (only?) a game (class = "habitat") and be stored in nested sequences, but for real dealing with taxonomy of animals may need a semi-pro database first thing (and occasionally forking the db into subclasses). Etc. I suggest working on the class stuff first, and use sequences to store the data (even then.. split(), store(), load(), etc).

Kat

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

14. Re: fake class in OE

mitgedanken said...

Only a hint

Namespaces can be used in routine_id()

Please, continue.

mitgedanken said...

But for now there is no way to get the namespace programmatically.
A constant must be set instead.

I hope i understand your meaning and i do not wander outside scope...

Ah, but there is if you use a preprocessor that re-writes the code. I made "varname" and varname access the same data for small amounts of shared_vars by simply using a case stack. And to know the name of the variable in OE's type system, you need only comment out the programmer's declaration, and insert your own unique type, which only that varname is type-checked with, ergo in that type-check code, it can be only one varname.

On startup, all the known data can be loaded as strings (vs enumerations in code?), and a case stack can equate "varname" and varname if necessary. Sure it can be done differently if OE/Phix had a variable_id().

Kat

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

15. Re: fake class in OE

katsmeow said...
mitgedanken said...

Namespaces can be used in routine_id()

Please, continue.

Yes, as of I think 4.0 (maybe it was 4.1) you can call routine_id() with a namespace:

include std/map.e 
include std/socket.e as sock 
 
? routine_id( "map:new" ) -- default namespace 
? routine_id( "sock:create" ) -- custom namespace 

-Greg

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

16. Re: fake class in OE

ghaberek said...

[...]

include std/map.e 
include std/socket.e as sock 
 
? routine_id( "map:new" ) -- default namespace 
? routine_id( "sock:create" ) -- custom namespace 

-Greg

Yes, that's what I mean.
Then, you can use a constant to concat

constant ns = "sock:" 
sequence from_somewhere = "create" 
routine_id(ns & from_somewhere) -- equal to "sock:create" 

This is how I implement 'dynamic' plain OE modules.

Sara |mitgedanken|

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

17. Re: fake class in OE

Only a hint
Pass By Reference OOP Style

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

18. Re: fake class in OE

Only a hint, too

class Dude 
  public: 
    string fname, lname 
    atom age 
    procedure introduce() 
        printf(1,"Hi I'm %s %s and I use Phix!\n", {fname, lname})  
    end procedure 
end class 
      
Dude my_dude = new({"John", "Smith", 32})    
Dude cool_dude = new({"Ronald", "Weidner", 745}) 
      
my_dude.age = 22 
printf(1,"%s %s is %d\n",{my_dude.fname,my_dude.lname,my_dude.age}) 
cool_dude.introduce() 
      
{} = wait_key()   
new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu