The "IT DOESN'T WORK!" thread

A place to discuss the implementation and style of computer programs.

Moderators: phlip, Prelates, Moderators General

Re: The "IT DOESN'T WORK!" thread

Postby Cosmologicon » Mon Dec 05, 2011 7:55 pm UTC

EvanED wrote:Python doesn't have true global variables, only module-level variables. "Globals" defined in one module aren't visible in another.

If module m defines a "global" v (just with something like v=10 outside of a function), then other modules that import m can refer to it via m.v, but you need the module qualification just like anything else. (I think that the generally-ill-advised import * from m would make v available unqualified.)

It's from m import *. And the perfectly fine from m import v will also allow you to refer to v unqualified.
User avatar
Cosmologicon
 
Posts: 1806
Joined: Sat Nov 25, 2006 9:47 am UTC
Location: Cambridge MA USA

Re: The "IT DOESN'T WORK!" thread

Postby Windowlicker » Wed Dec 07, 2011 12:04 pm UTC

Working on a Haskell implementation of code war.. it's mostly done. VM is working, parser is working, a GUI is well on the way.. the only place I'm having trouble is reading warriors from files and adding them to the core. I'm getting an infinite loop, and I think it's in here:

Code: Select all
makeState :: IO [Warrior] -> IO System -> IO System
makeState inp state = do
    i <- inp
    st <- state
    if length i == 0 then
        return st
    else
        makeState (return (tail i)) $ genState (head i) st


I've tried a few subtle variations of this, but I still can't get it to work.

What I'd like to do is
Spoiler:
Code: Select all
makeState :: IO [Warrior] -> IO System -> IO System
makeState [] state = state
makeState (x:xs) state = do
    y <- x
    st <- state
    makeState xs $ genState y st

but.. you know, there's that whole can't pattern-match with monads thing.

genState is genState :: Warrior -> System -> IO System. It works when used outside this context, so I don't think it's where the error lies. It takes the warrior and system, then adds the warrior to a random location and returns the resulting system. I.. cannot figure out why this doesn't work.
Windowlicker
 
Posts: 323
Joined: Wed Dec 23, 2009 6:57 pm UTC
Location: St Andrews, Scotland

Re: The "IT DOESN'T WORK!" thread

Postby phlip » Wed Dec 07, 2011 1:16 pm UTC

Sounds like a job for a fold...
Code: Select all
makeState inp state = do
    i <- inp
    st <- state
    foldlM (flip genState) st i

That said, I'm not sure what's wrong with your code... are you sure it's infinite-looping? How big is the list you're passing for inp? Could be it's just taking a while to run... you can move up from O(n2) to O(n) by replacing "length i == 0" with "null i" (assuming genState is O(1))...
While no one overhear you quickly tell me not cow cow.
but how about watch phone?
User avatar
phlip
Restorer of Worlds
 
Posts: 7172
Joined: Sat Sep 23, 2006 3:56 am UTC
Location: Australia

Re: The "IT DOESN'T WORK!" thread

Postby Windowlicker » Wed Dec 07, 2011 1:43 pm UTC

I thought a fold might have been more.. elegant, but I couldn't work out if it was exactly what I wanted.
I'm assuming it's an infinite loop. Compiling the code with ghc and running it gives the output "Main: <<loop>>". I couldn't find any information about it, so I could be wrong with my assumption.
The lists are only 2/3 long at the moment, so it shouldn't be taking too long to process them.
I've tried the fold, and it's producing the same output. Ah, I don't know.

It's difficult to tell, 'cause we have a function called loop also. The test code that worked was:

Code: Select all
main :: IO ()
main = do
    st <- genState dwarf init_state
    st' <- genState dwarf1 st
    loop st' 0


Dwarf and dwarf1 are test warriors, hard-coded into another module.. they're what I'm trying to load from files.
The main loop that doesn't work is:

Code: Select all
main :: IO ()
main = do
    sys <- loadSystem
    loop sys 0


Where loadSystem :: IO System.
Windowlicker
 
Posts: 323
Joined: Wed Dec 23, 2009 6:57 pm UTC
Location: St Andrews, Scotland

Re: The "IT DOESN'T WORK!" thread

Postby Jof16's » Wed Dec 07, 2011 9:32 pm UTC

Cosmologicon wrote:
EvanED wrote:Python doesn't have true global variables, only module-level variables. "Globals" defined in one module aren't visible in another.

If module m defines a "global" v (just with something like v=10 outside of a function), then other modules that import m can refer to it via m.v, but you need the module qualification just like anything else. (I think that the generally-ill-advised import * from m would make v available unqualified.)

It's from m import *. And the perfectly fine from m import v will also allow you to refer to v unqualified.


Okay, so I had to rewrite the entire thing to allow for the variables to be accessible from the module.
Now I have a question. Several of the variables need to be changed when a certain button is pushed. However, using 'variable = 10' inside the functions that these buttons call doesn't seem to be working. Am I doing something wrong?

And thank y'all for the help so far.
Jof16's
 
Posts: 84
Joined: Mon Jun 14, 2010 4:08 pm UTC

Re: The "IT DOESN'T WORK!" thread

Postby Windowlicker » Wed Dec 07, 2011 9:47 pm UTC

If you're trying to access a global variable (let's say x), you'll need to include the line "global x" inside the function definition before you can change it. I believe you can read them without this call.
I haven't used this with variables from another module, but based on what Evan's said it might be something like "global m.v".
Python namespacing/scope.. takes a bit of getting used to.
Windowlicker
 
Posts: 323
Joined: Wed Dec 23, 2009 6:57 pm UTC
Location: St Andrews, Scotland

Re: The "IT DOESN'T WORK!" thread

Postby Jof16's » Wed Dec 07, 2011 9:53 pm UTC

Right now, I'm using the ' from x import * ' method. I am using 'global v' inside the function, but it isn't changing the variable.
and yes, you can read the variables without the global declaration (is that the right word?)

Yes, it does.
Jof16's
 
Posts: 84
Joined: Mon Jun 14, 2010 4:08 pm UTC

Re: The "IT DOESN'T WORK!" thread

Postby Cosmologicon » Wed Dec 07, 2011 10:00 pm UTC

Windowlicker wrote:If you're trying to access a global variable (let's say x), you'll need to include the line "global x" inside the function definition before you can change it. I believe you can read them without this call.
I haven't used this with variables from another module, but based on what Evan's said it might be something like "global m.v".
Python namespacing/scope.. takes a bit of getting used to.

Yeah it does take some getting used to, but at least it's consistent. If you're referring to a variable as m.v, you don't need to specify that it's a global. As long as you never change the value of m within the function (m = .... or something like that) then m is automatically a global, referring to the same thing it refers to outside the function. And since m is a global referring to the module, m.v refers to the property v of the module m. So these work just fine:

Code: Select all
import m
def setv(value):
    m.v = value

Code: Select all
class X: pass
m = X()
def setv(value):
    m.v = value

But for these you need to specify global:
Code: Select all
from m import v
def setv(value):
    global v
    v = value

Code: Select all
v = 0
def setv(value):
    global v
    v = value

I suspect, however, that Jof16 is doing it "wrong". The global keyword is probably not the "right" way to handle this case (although I use it all the time when it's necessary). A minimal code example might help.
User avatar
Cosmologicon
 
Posts: 1806
Joined: Sat Nov 25, 2006 9:47 am UTC
Location: Cambridge MA USA

Re: The "IT DOESN'T WORK!" thread

Postby Windowlicker » Wed Dec 07, 2011 10:04 pm UTC

The third example was what I was aiming for, just with.. well, mistakes in. The first way is the way I'd do it myself, but for some reason I've recently become very into qualifying imports in every language I'm using..
Windowlicker
 
Posts: 323
Joined: Wed Dec 23, 2009 6:57 pm UTC
Location: St Andrews, Scotland

Re: The "IT DOESN'T WORK!" thread

Postby Jof16's » Wed Dec 07, 2011 10:12 pm UTC

Here's some of the code:

Code: Select all

def buttonSword():
    global weaponDamage
    global weaponAmmo

    weaponDamage = 5
    text.insert(END, "You have chosen a sword.\n")
    text.insert(END, "It can do up to " + str(weaponDamage) + " points of damage.\n")
    text.insert(END, "To change your weapon, press one of the weapon buttons\nbelow.\n\n")
    weaponAmmo = ammo(weaponDamage, text)


weaponDamage has a value of 0 in the module that contains all the global variables.
I keep getting the error at this line:
Code: Select all
zDamage = randint(1, weaponDamage)


There are also several others that won't change, but they won't throw errors because it just refers back to the original value each time through.
Jof16's
 
Posts: 84
Joined: Mon Jun 14, 2010 4:08 pm UTC

Re: The "IT DOESN'T WORK!" thread

Postby Cosmologicon » Wed Dec 07, 2011 10:16 pm UTC

Windowlicker wrote:The third example was what I was aiming for, just with.. well, mistakes in. The first way is the way I'd do it myself, but for some reason I've recently become very into qualifying imports in every language I'm using..
Let's be clear, the first and third examples are not quite doing the same thing. If you use "import m" and then set m.v, you're actually changing the value of the property v in module m. If you use "from m import v", then you're creating an identifier v that refers to the same object as property v of module m, but then if you reassign v, you're no longer referring to that same object. The value of m.v will be unchanged. Here's an example. Say my m.py file consists just of "v = 0":
Code: Select all
>>> import m
>>> m.v = 1
>>> import m
>>> m.v
1

Code: Select all
>>> from m import v
>>> v = 1
>>> from m import v
>>> v
0
Of course, if you never change the value of v, then it's not an issue.
User avatar
Cosmologicon
 
Posts: 1806
Joined: Sat Nov 25, 2006 9:47 am UTC
Location: Cambridge MA USA

Re: The "IT DOESN'T WORK!" thread

Postby Cosmologicon » Wed Dec 07, 2011 10:18 pm UTC

Jof16's wrote:Here's some of the code:

Code: Select all

def buttonSword():
    global weaponDamage
    global weaponAmmo

    weaponDamage = 5
    text.insert(END, "You have chosen a sword.\n")
    text.insert(END, "It can do up to " + str(weaponDamage) + " points of damage.\n")
    text.insert(END, "To change your weapon, press one of the weapon buttons\nbelow.\n\n")
    weaponAmmo = ammo(weaponDamage, text)


weaponDamage has a value of 0 in the module that contains all the global variables.

How are you initially defining weaponDamage within the module that contains buttonSword? Are you saying "from globalvars import weaponDamage"? If so, then take a look at my last post, this function of yours is not actually setting the variable within that module. I think it would be better if you just say "import globalvars" and then within buttonSword set globalvars.weaponDamage.
User avatar
Cosmologicon
 
Posts: 1806
Joined: Sat Nov 25, 2006 9:47 am UTC
Location: Cambridge MA USA

Re: The "IT DOESN'T WORK!" thread

Postby Jof16's » Wed Dec 07, 2011 10:21 pm UTC

I'm using ' from Game_config import * '

Okay. I'll go try that.

Thank you.


EDIT: Yay! It works!
Thank y'all for the help.
Also, if you would please check out my thread. I've still got some problems that need solving. Thanks in advance. :)
Jof16's
 
Posts: 84
Joined: Mon Jun 14, 2010 4:08 pm UTC

Re: The "IT DOESN'T WORK!" thread

Postby Windowlicker » Thu Dec 08, 2011 2:56 pm UTC

Cosmologicon wrote:
Windowlicker wrote:The third example was what I was aiming for, just with.. well, mistakes in. The first way is the way I'd do it myself, but for some reason I've recently become very into qualifying imports in every language I'm using..
Let's be clear, the first and third examples are not quite doing the same thing. If you use "import m" and then set m.v, you're actually changing the value of the property v in module m. If you use "from m import v", then you're creating an identifier v that refers to the same object as property v of module m, but then if you reassign v, you're no longer referring to that same object. The value of m.v will be unchanged. Here's an example. Say my m.py file consists just of "v = 0"
Aaah, of course. This is useful information.. Despite the fact that I have been and currently am working with Python on a few projects, I've not come across the need to edit variables in another module. But, the more you know, eh?

As for my Haskell issue, I got that fixed: it turns out the error was a few lines later, I'd declared "let war = war ++ [listWarriors]" or something like that to build the list. Problem solved, easy change to "let war' = war ++ [listWarriors]". Ah, haskell.
Windowlicker
 
Posts: 323
Joined: Wed Dec 23, 2009 6:57 pm UTC
Location: St Andrews, Scotland

Re: The "IT DOESN'T WORK!" thread

Postby headprogrammingczar » Thu Dec 08, 2011 5:21 pm UTC

If you REALLY don't want to name variables "war'", you can do

Code: Select all
x # f = f x

war ++ [listWarriors] $ \war ->
...


You would essentially be doing a CPS-transform of the code around that 'let'.
<quintopia> You're not crazy. you're the goddamn headprogrammingspock!
<Weeks> You're the goddamn headprogrammingspock!
<Cheese> I love you
User avatar
headprogrammingczar
 
Posts: 3024
Joined: Mon Oct 22, 2007 5:28 pm UTC
Location: Beaming you up

Re: The "IT DOESN'T WORK!" thread

Postby EvanED » Sun Dec 25, 2011 7:12 am UTC

How can I make diff ignore all whitespace differences, even across lines?

edit Here's my "solution": diff --ignore-all-space <(cat $file1 tr -d "\n") <(cat $file2 tr -d "\n").
EvanED
 
Posts: 4133
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI

Re: The "IT DOESN'T WORK!" thread

Postby not baby Newt » Sun Dec 25, 2011 11:45 am UTC

The googles suggests you shouldn't need to go that far. But I haven't tried it out and you already use the option mentioned.
http://ss64.com/bash/diff.html wrote:The `-w' and `--ignore-all-space' options are stronger than `-b'. They ignore difference even if one file has white space where the other file has none. "White space" characters include tab, newline, vertical tab, form feed, carriage return, and space; some locales may define additional characters to be white space.
not baby Newt
 
Posts: 109
Joined: Wed Feb 03, 2010 11:30 pm UTC

Re: The "IT DOESN'T WORK!" thread

Postby EvanED » Sun Dec 25, 2011 5:12 pm UTC

Yeah, that doesn't work, at least on my (old, RHEL5-supplied) version of coreutils:

Code: Select all
$ diff -w --ignore-all-space <(echo "ab") <(echo "a\nb")
1c1,2
< ab
---
> a
> b


OTOH, my man page says
Code: Select all
       --ignore-all-space
              Ignore white space when comparing lines.

which is actually correct, I guess.
EvanED
 
Posts: 4133
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI

Re: The "IT DOESN'T WORK!" thread

Postby Aschey » Wed Jan 04, 2012 11:04 pm UTC

I just installed Python (for Mac), typed in a simple command, print 2 + 2, saved the file, and tried to run it by dragging the file into the Python Launcher. No matter what I try, I keep getting a syntax error in Terminal. I checked my syntax, tried other basic commands, and keep getting the same error. Anyone know what's up? Thanks.
Aschey
 
Posts: 2
Joined: Wed Jan 04, 2012 10:54 pm UTC

Re: The "IT DOESN'T WORK!" thread

Postby TheChewanater » Thu Jan 05, 2012 7:29 pm UTC

"print 2 + 2" is not valid in newer versions of python, so you may need to write it as a function - "print(2 + 2)". Can you post the error you're getting, and the version of Python you're using?
ImageImage
http://internetometer.com/give/4279
No one can agree how to count how many types of people there are. You could ask two people and get 10 different answers.
User avatar
TheChewanater
 
Posts: 1286
Joined: Sat Aug 08, 2009 5:24 am UTC
Location: lol why am I still wearing a Santa suit?

Re: The "IT DOESN'T WORK!" thread

Postby Aschey » Thu Jan 05, 2012 10:12 pm UTC

I'm not using the newest version, as it said it wasn't compatible with some things yet. But I fixed the issue, apparently I had to open a new window after opening the initial program. Not sure why that made a difference, but whatever. Thank you for the reply though.
Aschey
 
Posts: 2
Joined: Wed Jan 04, 2012 10:54 pm UTC

Re: The "IT DOESN'T WORK!" thread

Postby Jplus » Tue Jan 10, 2012 6:44 pm UTC

Aschey wrote:I just installed Python (for Mac), typed in a simple command, print 2 + 2, saved the file, and tried to run it by dragging the file into the Python Launcher. No matter what I try, I keep getting a syntax error in Terminal. I checked my syntax, tried other basic commands, and keep getting the same error. Anyone know what's up? Thanks.

As an aside, did you know Python is already installed on every mac by default?
Feel free to call me Julian. J+ is just an abbreviation.
Image coding and xkcd combined
User avatar
Jplus
 
Posts: 1554
Joined: Wed Apr 21, 2010 12:29 pm UTC
Location: classified

Re: The "IT DOESN'T WORK!" thread

Postby PerchloricAcid » Sun Jan 22, 2012 8:34 pm UTC

This isn't really a ''it doesn't work'' kind of problem/question, but I haven't found a thread dedicated to asking BASIC "how to" questions. If such a topic exists, please point it to me. My question isn't really worth opening a whole new topic.

So:
i have a .txt file with some integers. I'd like to write a program in C++ which would take every Nth integer from the file (and save it in another file). How?
PerchloricAcid
 
Posts: 339
Joined: Mon Aug 01, 2011 7:09 pm UTC

Re: The "IT DOESN'T WORK!" thread

Postby RoadieRich » Mon Jan 23, 2012 3:40 am UTC

PerchloricAcid wrote:This isn't really a ''it doesn't work'' kind of problem/question, but I haven't found a thread dedicated to asking BASIC "how to" questions. If such a topic exists, please point it to me. My question isn't really worth opening a whole new topic.

So:
i have a .txt file with some integers. I'd like to write a program in C++ which would take every Nth integer from the file (and save it in another file). How?

It's not a good idea to capitalise basic like that in a programming forum... it means something very different if you do that.

As to writing your program, you open a text editor, and type in the code.

This sounds suspiciously like a homework problem, for which we won't write the code for you, but we will help you, if you're willing to help yourself. To start with, show us what you can do.
roband wrote:Mav is a cow.

UniJam 2012: Inter-university Games Jam hosted by Nottingham Trent University DevSoc.
nlug: Nottingham Linux User Group
DevSoc: The Nottingham Trent University Software Development Society
User avatar
RoadieRich
The Black Hand
 
Posts: 1030
Joined: Tue Feb 12, 2008 11:40 am UTC
Location: Somewhere only we know

Re: The "IT DOESN'T WORK!" thread

Postby PerchloricAcid » Mon Jan 23, 2012 4:51 am UTC

I didn't even realize I capitalized it, however, I did it because I wanted to emphasize that my question wasn't worth a new topic. I am not the type of person that comes and asks other people to complete their homework or any kind of work for them. I just want some hints.
And, in case you saw my reply before the edit, I apologize for it being written in an unpleasant manner.


As to what I know:
I believe I could do this by using a for loop, where the increment would not be 1, but N. Perhaps I'd need to check whether I have reached the end of the file, so it might be better to use a while statement, although I wouldn't know how to check whether I have reached the end of the file (nor is it necessary).
I know how I'd save the taken values to another file, but I don't know how exactly would I "pick out" the values I want. I believe I might be needing "ifstream".
Of course, I'd open the file I'm reading from at first, I'd have a line which checks whether it really is opened, and close it in the end.
Last edited by PerchloricAcid on Mon Jan 23, 2012 1:35 pm UTC, edited 1 time in total.
PerchloricAcid
 
Posts: 339
Joined: Mon Aug 01, 2011 7:09 pm UTC

Re: The "IT DOESN'T WORK!" thread

Postby Xanthir » Mon Jan 23, 2012 5:51 am UTC

If you know how to do a for loop, and you know how to read a line from a file and write out to a different file, then the piece you're missing is the modulus operator "%". When you do "a % b", it returns the remainder of "a / b". This result cycles through the integers between 0 and b, so by using it in an IF statement you can achieve what you want.
(defun fibs (n &optional (a 1) (b 1)) (take n (unfold '+ a b)))
User avatar
Xanthir
My HERO!!!
 
Posts: 4308
Joined: Tue Feb 20, 2007 12:49 am UTC
Location: The Googleplex

Re: The "IT DOESN'T WORK!" thread

Postby PerchloricAcid » Mon Jan 23, 2012 1:23 pm UTC

The part which is bugging me is
but I don't know how exactly would I "pick out" the values I want

how exactly would I read from the file.

For I moment, I had thought that the modulus might come in handy, if I could somehow get the program to know that each of the integer has a value related to it's order. This value would be one for the first integer, two for the second, etc. If I could do that, I would definitely use the modulus, but I figured last night that there might be something simpler, because I'm not really sure about how to designate those values.
PerchloricAcid
 
Posts: 339
Joined: Mon Aug 01, 2011 7:09 pm UTC

Re: The "IT DOESN'T WORK!" thread

Postby Steax » Mon Jan 23, 2012 1:47 pm UTC

Can you tell us more about what you've done before, or how far you've learned? It helps a lot.

Typically in your situation I'd do this, in psudeocode:

Code: Select all
loop = true;
i = 0;
while(loop){
   if(get_file_line(i) == EOF){ loop = false; }
   if(loop % N == 0){
      save_to_other_file(get_file_line(i));
   }

   line++;
}


(I'm leaving it in psudeocode so it doesn't get to instructive; it may not be the best way to do it. It's just how I'd approach it if I didn't know anything else about what it would technically require. You could also count the lines and do a for loop with a different increment, yes, if you'd like, but I prefer flexibility, and hence looping through every line. Also, I dislike break.)
In Minecraft, I use the username Rirez.
User avatar
Steax
SecondTalon's Goon Squad
 
Posts: 3037
Joined: Sat Jan 12, 2008 12:18 pm UTC

Re: The "IT DOESN'T WORK!" thread

Postby PerchloricAcid » Tue Jan 24, 2012 4:27 am UTC

Thank you, I'll try to make use of what you wrote. :)

Well...
I know about loops, I know about classes (irrelevant here, I believe), I know... well, basically, I know stuff I needed for this simulation of mine, and a tiny bit more. So I'll just say what my program does.
I have a simplified three-body simulation which asks the user for initial conditions, saves them to a file, uses them for calculating stuff (using the RK4 integration method, but I've also toyed with other integration methods), saves the results in another file (t, x, y, vx, vy, ax, ay - for each moment defined by the time step dt).
Other things I know are just things I have come across while searching for my_simulation-related stuff, can't think of anything specific.
PerchloricAcid
 
Posts: 339
Joined: Mon Aug 01, 2011 7:09 pm UTC

Re: The "IT DOESN'T WORK!" thread

Postby Yakk » Tue Jan 24, 2012 3:41 pm UTC

A good trick is to make your format a bit more readable.

As an example:
Code: Select all
[INITIAL]
T:=
X:=
Y:=
VX:=
XY:=
AX:=
AY:=
[TIMESTEP]
T:=
X:=
Y:=
VX:=
XY:=
AX:=
AY:=

Your reading code now looks like this:
Code: Select all
1: Look for next line that is [INITIAL] or [TIMESTEP].  Lines that aren't [INITIAL] or [TIMESTEP] are ignored.
2: Look for a line that looks like VALUE:=VALUE -- ie, look for the :=.  Lines that don't contain := are ignored.
3: Evaluate what the part after the := is.  Include error handling if it makes no sense.
4: What is the part before the := -- is it "Y", "T", "X", "VX", "VY", "AX" or "AY"?  For each of these cases, set some value in your program.

Sure, this involves some really simple string manipulation. But your data files are now far, far more human readable. And if something goes wrong with your code (an extra line is included, or missing) it will be far more obvious what happened. Oh, and you can even extend your file format -- adding ENERGY:= to the [INITIAL], for example, or what have you.

The important part is that the file format is human readable, however. That'll help you fix more bugs than anything else.
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.
User avatar
Yakk
Poster with most posts but no title.
 
Posts: 10422
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

Re: The "IT DOESN'T WORK!" thread

Postby Rysto » Wed Jan 25, 2012 1:02 am UTC

Ugh, I just found the following bug at work:

Code: Select all
    /* Note that we have to be very careful to not allow foo to reach 0.  If it does all hell will break loose! */
    while (foo > 0 && other_conditions()) {
         foo--;
         /* ... */


Yes, the comment was completely accurate.
Rysto
 
Posts: 1443
Joined: Wed Mar 21, 2007 4:07 am UTC

Re: The "IT DOESN'T WORK!" thread

Postby EvanED » Wed Jan 25, 2012 1:55 am UTC

Code: Select all
"format ‘%s’ expects type ‘char*’, but argument 3 has type ‘int’"

is a fun warning. Especially when you look at it and find out that there's no way it could work.

At least it was only in "this will never run"-type code. (Which is probably why it lived.)
EvanED
 
Posts: 4133
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI

Re: The "IT DOESN'T WORK!" thread

Postby PerchloricAcid » Wed Jan 25, 2012 8:51 pm UTC

Thanks for the help, guys.
I solved my problem :)
[However, later on I figured out that there was a more elegant way to do what I wanted, so I basically didn't even need this what I asked for, but practice is always good anyway.]
PerchloricAcid
 
Posts: 339
Joined: Mon Aug 01, 2011 7:09 pm UTC

Re: The "IT DOESN'T WORK!" thread

Postby Shivahn » Thu Jan 26, 2012 6:39 pm UTC

Hey, I'm having a ton of trouble with a very simple Scheme function. I want to make a function that takes a function and a number, and returns the function that performs that function on itself that number of times. In other words, given a function f and a number n=2, it should return f(f(x)). Given g and 5 it should return g(g(g(g(g(x))))). Here is my code:

Code: Select all
(define (repeat f n) (lambda (x) (if (= n 1) (f x) (f (repeat f (- n 1))))))
(define (square x) (* x x))


The square stuff is there for the testing. Now, when I type in ((repeat square 2) 5) what I expect to happen is for the interpreter to perform square on the value of square 5, which should be 25, so it should return 625 total. Instead what I get is "*: expects type <number> as 1st argument, given: #<procedure>; other arguments were: #<procedure>". That's within the body of the square function. When I go through the debugger, I notice that the repeat function is not recursively calling itself, so presumably it's returning the function (square (repeat f (- n 1)) or something similar. Am I right in thinking this? Does anyone know how to force the repeat function to recurse? And more importantly, can someone explain to me why it's not? (If that's what it's doing, of course.)
User avatar
Shivahn
 
Posts: 2193
Joined: Tue Jan 06, 2009 6:17 am UTC

Re: The "IT DOESN'T WORK!" thread

Postby Yakk » Thu Jan 26, 2012 6:46 pm UTC

First, learn how to indent. Code on one line is not easier to read, and code should be written to be read.
Code: Select all
(define
  (repeat f n)
  (lambda
    (x)
    (if
      (= n 1)
      (f x)
      (f
        ( repeat f (- n 1) )
      )
    )
  )
)

So, what does this do? It returns a lambda that takes 1 parameter. This lamba then evaluates if n equals 1. If n equals one, it returns f(x).

If lambda does not equal 1, it returns (f (repeat f (- n 1))). First, notice the lack of an x in that expression.

Second, what is the return type of (repeat f integer)? You are explicitly calling f with this argument. Write out the type. Is there any way you can get from this type to the type you want?

(Do you know how to write out types of functions, like in mathematics?)
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.
User avatar
Yakk
Poster with most posts but no title.
 
Posts: 10422
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

Re: The "IT DOESN'T WORK!" thread

Postby Shivahn » Thu Jan 26, 2012 8:47 pm UTC

Sorry about the indentation. I have a really terrible habit of ignoring good practices when writing up smaller bits of code.

I fixed it by making it

Spoiler:
Code: Select all
(define
  (repeat f n)
  (define
    (repeath f n x)
    (if
     (= n 1)
     (f x)
     (repeath f (- n 1) x)
     )
    )
  (lambda
    (x)
    (if
      (= n 1)
      (f x)
      (f
        ( repeath f (- n 1) x)
      )
    )
  )
)


But I'm not sure I understand everything you said, or did this the "right" way, so I want to be clear. Before, I know I was calling f on the function returned by (repeat f integer). I feel like I'm missing something with the type - isn't the type returned simply a function that (takes a function that takes a function) that takes x? I don't know what I changed here, other than making it so that it's using the same x all the way down. I feel like I'm missing something critical now.

And I don't know how to write out types of functions. While I've coded off and on for some time, it's only now that I'm getting into the theory and actual meanings behind the words and academics and all, so my background knowledge can be pretty lacking in certain areas. If there's a quick tutorial you have or something, I'd love to read it.
User avatar
Shivahn
 
Posts: 2193
Joined: Tue Jan 06, 2009 6:17 am UTC

Re: The "IT DOESN'T WORK!" thread

Postby Yakk » Thu Jan 26, 2012 10:04 pm UTC

So, when you have a function from Real to Integers, the function's type is R->Z (where R is real, and Z is integers). You'd write this as f:R->Z in mathematical notation.

In C++, the function might be declaired as R foo(Z), or auto foo(Z)->R -- that last one being more similar to mathematical notation.

What you did works, right? You now feed x back into the lambda you get from your recursive call.

The type of your repeat is then:
(A->A, N)->(A->A)
where A is some unknown type, and N is your "repeat count".

A more amusing way to write repeat could be:
(A->A)->(N->(A->A))
which is logically similar, except now repeat takes a function from A to A, and returns a function that takes the number of repeats and outputs that function from A->A.

In a sense, this takes f(x) as input, and outputs the function g, where g(n) = f^n.

Another amusing way to write repeat is like this:
N->((A->A)->(A->A))
which would be a repeat function that takes a parameter of the number of repeats, and returns a function that takes an A->A function and returns a function that repeats it n times.

This repeater generates the "to the power of n" operator.

Writing both of these could be illuminating.
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.
User avatar
Yakk
Poster with most posts but no title.
 
Posts: 10422
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

Re: The "IT DOESN'T WORK!" thread

Postby EvanED » Thu Jan 26, 2012 10:23 pm UTC

Yakk wrote:The type of your repeat is then:
(A->A, N)->(A->A)
where A is some unknown type, and N is your "repeat count".

Better would be to parenthesize it as
Code: Select all
( (A->A), N ) -> (A->A)


Pairing binds tighter than function application in every typed functional language I know, so (A -> A, N) would be interpreted as a function of one argument that returns a pair. While there's nothing fundamentally wrong with doing the other thing, it goes against expectations heavily. At least for people who have the background to have expectations.

A more amusing way to write repeat could be:
(A->A)->(N->(A->A))
which is logically similar, except now repeat takes a function from A to A, and returns a function that takes the number of repeats and outputs that function from A->A.

This is called Currying, after Haskell Curry. (The same dude that the Haskell language is named off of.)

Unfortunately, Lisps aren't a very good language for curring in without writing or using some supporting code to convert a non-curried function to a curried one. I'm not saying don't write them, but expect it to be annoying. For instance, you'd have to say ((repeat square) 3) instead of (repeat square 3).
EvanED
 
Posts: 4133
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI

Re: The "IT DOESN'T WORK!" thread

Postby headprogrammingczar » Thu Jan 26, 2012 10:53 pm UTC

Not strictly relevant, as the problem has already been solved, but lispy indentation style goes more like this, with the lisp programmer reading indentation instead of parens:
Code: Select all
(define (repeat f n)
  (lambda (x)
    (if (= n 1)
      (f x)
      (f (repeat f (- n 1))))))
<quintopia> You're not crazy. you're the goddamn headprogrammingspock!
<Weeks> You're the goddamn headprogrammingspock!
<Cheese> I love you
User avatar
headprogrammingczar
 
Posts: 3024
Joined: Mon Oct 22, 2007 5:28 pm UTC
Location: Beaming you up

Re: The "IT DOESN'T WORK!" thread

Postby EvanED » Thu Jan 26, 2012 11:26 pm UTC

FWIW when I was doing a bunch of Lisp programming I came to despise the "lispy" indentation style and usually use something more like Yakk's. The "indentation is all you need" is a bit of a pipe dream, and it makes editing harder.

But this is more a conversation for the religious wars forum.
EvanED
 
Posts: 4133
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI

PreviousNext

Return to Coding

Who is online

Users browsing this forum: No registered users and 6 guests