POV-Ray : Newsgroups : povray.off-topic : C# 4.0 Default parameters Server Time
6 Sep 2024 11:16:12 EDT (-0400)
  C# 4.0 Default parameters (Message 47 to 56 of 56)  
<<< Previous 10 Messages Goto Initial 10 Messages
From: Darren New
Subject: Re: C# 4.0 Default parameters
Date: 4 Feb 2009 19:06:26
Message: <498a2d82$1@news.povray.org>
Orchid XP v8 wrote:
> Darren New wrote:
>> Technically, I would think you could have a curried function in a 
>> language with named parameters pretty easily.
> 
> Yeah, I don't see why not. It's only a shortcut for creating a closure...

I mean, if you have named parameters, it would seem pretty easy to have a 
syntax for currying on any parameter.

>> That's where they're used in C#.
> I didn't think C# had curried functions like my example.

Yeah. Brain-oh. It does have closures, tho. Isn't that a very similar thing?

> Does this transformation happen at compile-time or runtime?

As far as I understand it, the AST is generated at compile time, but you can 
compile it into actual machine code at runtime.

-- 
   Darren New, San Diego CA, USA (PST)
   "Ouch ouch ouch!"
   "What's wrong? Noodles too hot?"
   "No, I have Chopstick Tunnel Syndrome."


Post a reply to this message

From: Darren New
Subject: Re: C# 4.0 Default parameters
Date: 4 Feb 2009 19:09:25
Message: <498a2e35$1@news.povray.org>
Warp wrote:
>   What if you want to call the function (through the pointer) for different
> objects?

I can't think of a convenient way offhand to do this in C#. I think here 
you'd likely fall back to a fixed-named function and then subclass objects 
(or inherit from interfaces) to do that.

I never found the need to orthogonally specify a function and an object to 
call it on, altho I imagine it might come up sometimes.

-- 
   Darren New, San Diego CA, USA (PST)
   "Ouch ouch ouch!"
   "What's wrong? Noodles too hot?"
   "No, I have Chopstick Tunnel Syndrome."


Post a reply to this message

From: nemesis
Subject: Re: C# 4.0 Default parameters
Date: 4 Feb 2009 20:44:48
Message: <498a4490$1@news.povray.org>
Warp wrote:
>   So you take what's great about OOP, rename it, and then say you hate OOP
> and that it sucks, and that your own version is so much better.

The way code flows, yes, it's much better.


Post a reply to this message

From: Darren New
Subject: Re: C# 4.0 Default parameters
Date: 4 Feb 2009 20:57:53
Message: <498a47a1@news.povray.org>
Mike Raiford wrote:
> No, I don't think you can. The closest you could get would be something 
> like a multicast delegate. But, then you really cannot get a return value.

I think you'd have to do something like this. First, you need an interface 
that defines all the possible functions you can call this way. That would be 
the equivalent of making all the objects subclasses of the same class in C++.

interface Istuff {
   int xyz(int x);
   int pdq(int x);
}

// Then a class that inherits from Istuff
class Mine : Istuff {
   int xyz(int x) { return x + 1; }
   int pdq(int x) { return x - 1; }
}

// Declare the type of a delegate that takes the object and integer and runs 
something.
delegate int do_it(Istuff on_what, int with_what);

// Declare two delegates, initializing them. One calls xyz, one calls pdq.
do_it use_xyz = ((Istuff on_what, int with_what) => on_what.xyz(with_what));
do_it use_pdq = ((Istuff on_what, int with_what) => on_what.pdq(with_what));

// Pick which one you want
void go_run_a_function(
   inputted_bool ? use_xyz : use_pdq,
   Istuff some_object, int parameter);


So, you can do it, basically by changing
   blah(object, parameter)
into
   object.blah(parameter)
with a lambda. But it's messy. Probably about as messy as going the other 
way in C++.  There's probably some fancy thing with generics you could do too.


-- 
   Darren New, San Diego CA, USA (PST)
   "Ouch ouch ouch!"
   "What's wrong? Noodles too hot?"
   "No, I have Chopstick Tunnel Syndrome."


Post a reply to this message

From: Warp
Subject: Re: C# 4.0 Default parameters
Date: 5 Feb 2009 05:47:17
Message: <498ac3b5@news.povray.org>
Darren New <dne### [at] sanrrcom> wrote:
> Warp wrote:
> >   What if you want to call the function (through the pointer) for different
> > objects?

> I can't think of a convenient way offhand to do this in C#. I think here 
> you'd likely fall back to a fixed-named function and then subclass objects 
> (or inherit from interfaces) to do that.

  But the whole idea with function pointers is that you can call different
functions (which have the same signature) from the same code.

  In C++ templates have mostly replaced the need for this (or at least made
it way easier in syntax), but not completely.

-- 
                                                          - Warp


Post a reply to this message

From: Darren New
Subject: Re: C# 4.0 Default parameters
Date: 5 Feb 2009 14:26:06
Message: <498b3d4e$1@news.povray.org>
Warp wrote:
>   But the whole idea with function pointers is that you can call different
> functions (which have the same signature) from the same code.

You can do that. What you can't do (easily) is have a function pointer to an 
instance method that doesn't include the object the instance is invoked on.

In other words, there's no way to declare a function pointer (aka delegate) 
that allows you to declare the "this" parameter outside the normal argument 
list. So you can't say "xyz.my_delegate(27)". You have to invoke 
"my_delegate(xyz, 27)", at which point obviously my_delegate can't point to 
a static function that doesn't have a "this" argument. The terrors of 
distinguished caller syntax.

You can call any function that has the same signature. If you declare
   delegate int xyz(float x);
   xyz fun_ptr;
then any variable of type xyz (such as fun_ptr) can accept a pointer to any 
function that takes a float as an argument and returns an integer. It 
doesn't matter if it's a static function or an instance function, but *if* 
it's an instance function, you have to pass in the instance when you create 
the pointer, because there's no place else to do it - nowhere in the 
declaration of type "xyz" is there a mention of the instance object, so if 
it's an instance function, you have to bind the instance before you assign 
it to the pointer.  I.e., in C++, if you have a pointer to a member 
function, you can't invoke it without providing the member when you invoke 
it. In C#, if you have a pointer to a function, you have to provide the 
member it points to along with the function it points to when you create a 
pointer to a member function.

You cannot conveniently (i.e., without code) declare a pointer (or delegate) 
that points to an instance function without providing the instance. You 
*can* declare a function that takes an instance and arguments and invokes 
the appropriate function, then put that in a delegate and pass in which 
object you want to use when you invoke it. I.e., you can write a one-liner 
that takes "this" from an argument and sticks it before the dot, and then 
assign that one-liner to a delegate.

Me, I'm having a hard time imagining a use-case for a pointer to a member 
function that *doesn't* carry an object reference with it. I.e., I can't 
think of functionality I'd be coding where I know what function I want to 
call when I create the pointer, but I don't know what object I want to call 
it on. Can you offer an example?


-- 
   Darren New, San Diego CA, USA (PST)
   "Ouch ouch ouch!"
   "What's wrong? Noodles too hot?"
   "No, I have Chopstick Tunnel Syndrome."


Post a reply to this message

From: John VanSickle
Subject: Re: C# 4.0 Default parameters
Date: 5 Feb 2009 21:34:57
Message: <498ba1d1$1@news.povray.org>
nemesis wrote:
> Darren New escreveu:
>> Mike Raiford wrote:
>>> That is how C# is now. Sometimes it would be nice just to have one 
>>> function with defaults, rather than 3 overloads of the same function 
>>> that simply delegate back to the "full featured" function.
>>
>> No, i mean instead of
>>   job.print(orient:landscape, copies:2, paper:A4)
>> the suggestion it that it's much more OO to say
>>   job.initialize()
>>   job.orient(landscape)
>>   job.copies(2)
>>   job.paper(A4)
>>   job.print()
> 
> More OO, or more assemblyish?  I mean, you individually feed the stack 
> and then call a function using those arguments already in the stack. ;)

Some class designers would make most of the member functions in class 
PrintJob return a reference to the class so that this could be one line:

job.initialize().orient(landscape).copies(2).paper(A4).print();

Of course, there would also be interminable debate about whether there 
should be an initialize() member in any C++ class, and I'm sure that 
some would want to override the streaming operator so that it could be 
used to feed some of the parameters to the PrintJob class.

Regards,
John


Post a reply to this message

From: Darren New
Subject: Re: C# 4.0 Default parameters
Date: 5 Feb 2009 22:04:56
Message: <498ba8d8@news.povray.org>
John VanSickle wrote:
> Some class designers would make most of the member functions in class 
> PrintJob return a reference to the class so that this could be one line:
> 
> job.initialize().orient(landscape).copies(2).paper(A4).print();

Yeah. The person I saw advocating this also recommended command/query 
separation, so anything that sets a parameter wouldn't be able to return a 
value.  It would be interesting to know what he'd think of this sort of 
chaining, tho, which doesn't seem to violate the spirit of C/Q.

-- 
   Darren New, San Diego CA, USA (PST)
   "Ouch ouch ouch!"
   "What's wrong? Noodles too hot?"
   "No, I have Chopstick Tunnel Syndrome."


Post a reply to this message

From: Warp
Subject: Re: C# 4.0 Default parameters
Date: 6 Feb 2009 09:18:04
Message: <498c469c@news.povray.org>
Darren New <dne### [at] sanrrcom> wrote:
> Yeah. The person I saw advocating this also recommended command/query 
> separation, so anything that sets a parameter wouldn't be able to return a 
> value.

  So if setting a parameter to a given value can fail, you can't check
the success/failure of the function call by having the function return
eg. a boolean value informing of this, but instead you have to write a
separate function which you have to call in order to query whether the
operation was successful or not? And this for each such parameter which
can fail?

  This presents a multitude of problems. For instance, the class would
have to store booleans for each parameter somewhere, so that the "did
the setting of that parameter succeed?" function can return it.

  What if the success query function is called *before* the setting of
the parameter function is called? Can the return value have a meaningful
interpretation anymore?

-- 
                                                          - Warp


Post a reply to this message

From: Darren New
Subject: Re: C# 4.0 Default parameters
Date: 6 Feb 2009 13:49:16
Message: <498c862c$1@news.povray.org>
Warp wrote:
>   So if setting a parameter to a given value can fail, you can't check
> the success/failure of the function call by having the function return
> eg. a boolean value informing of this, but instead you have to write a
> separate function which you have to call in order to query whether the
> operation was successful or not? And this for each such parameter which
> can fail?

Well, there's two kinds of "setting it failed". One is (for example) setting 
a printer to use a certain kind of paper. Here you can't tell before you try 
that it's going to fail (assuming it "fails" if that sort of paper isn't in 
the printer the moment you set it).

The other kind is (for example) popping the stack on an empty stack, which 
you can tell will fail before you even try it. In this case, it's considered 
a programming error on the part of the caller to even attempt to pop an 
empty stack.

The recommendation that queries and commands be separate is it keeps you 
from having to put it in a variable that's unrelated to the object you're 
calling. Why would the 'did the paper setting function work' value ever be 
stored in the local variables of the function that generates the report, 
rather than in the object that represents the printer itself?

It also means that you can have one part of you code intialize the printer 
and another part check it's ready to go, without passing printer-specific 
values around in code that hasn't anything to do with the printer. It's more 
a "big program" sort of technique, along the same lines as "each object 
should be responsible for only one thing" sort of thing. The object takes 
full responsibility for tracking all its state, and you query the object for 
its state every single time you need to know it. If you return status from 
mutating calls, you're passing responsibility for tracking the status back 
to the caller instead of encapsulating it in the object.

>   This presents a multitude of problems. For instance, the class would
> have to store booleans for each parameter somewhere, so that the "did
> the setting of that parameter succeed?" function can return it.

Right. Or, the caller has to do that when they call the function.

The function still has to save that information, because if setting the 
paper size failed, you can't print to the printer, right?  If you *can* 
print to the printer, then it isn't "did the paper setting fail?", but 
"after I told you to use A4, what paper size will you use?" It's only a 
"failure" if the caller can't accept the paper size the printer's ready to use.

For example: if you set the paper size, the object still has to know what 
the paper size is.  If you can have a type with a distinguished value (like 
NULL in C), you can have the function that returns the paper size return 
NULL if the paper size didn't get set correctly, for example.

Look at something like the getchar() function in C. How often do you use 
that where you don't have to assign it to a variable to use it? Not very 
often. You always wind up writing something like
   while ((c = getchar()) != EOF) { do something with c }

Instead, the recommendation is to use the equivalent of
   readchar();
   while (currentchar() != EOF) {
     do something with currentchar()
     and something else with currentchar()
     readchar();
   }

It's a little more verbose, but the "current character" stays with the 
object it's associated with. When you start putting distinguished-caller 
syntax in the mix, it becomes a lot easier to understand what's going on 
when you're in maintenance mode.  Like, say you're comparing two lists:

    one.initlist();
    two.initlist();
    while (one.curr() != two.curr()) {
      if (one.curr() < two.curr()) one.nextitem();
      else if (two.curr() < one.curr()) two.nextitem();
    }

If "nextitem" returned the next item of the list, the logic would be 
somewhat more convoluted, trying to keep the local variables synchronized 
with the contents of the lists, and it would be easy to accidentally assign 
two.nextitem() to m_one or something.


>   What if the success query function is called *before* the setting of
> the parameter function is called? Can the return value have a meaningful
> interpretation anymore?

I imagine it depends on the function. If it's initialized to a default that 
works (like whatever paper size happens to be loaded), then the "will this 
work" function would return true. If it's initialized to a value that's 
invalid (like the name of the file on a closed file handle) then the "will 
this work" function returns false.  The constructor has to assure that the 
query functions are valid, just like any other initialization the 
constructor needs to do.

-- 
   Darren New, San Diego CA, USA (PST)
   "Ouch ouch ouch!"
   "What's wrong? Noodles too hot?"
   "No, I have Chopstick Tunnel Syndrome."


Post a reply to this message

<<< Previous 10 Messages Goto Initial 10 Messages

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.