|
forums.silverfrost.com Welcome to the Silverfrost forums
|
View previous topic :: View next topic |
Author |
Message |
kaliuzhkin
Joined: 17 Sep 2012 Posts: 33
|
Posted: Sat Oct 21, 2017 8:24 pm Post subject: Function arguments |
|
|
Just a curiosity. It appears that you can't define an external function with no arguments.
My answer to an exercise in Fortran 95, Martin Counihan, Section 7.2, Exercises 7.A, page 114, Exercise 7.A10.
"Using RANDOM [rather, RANDOM_NUMBER], write an integer function
that will simulate the throw of two dice, adding their results. If
a double is thrown, an extra throw is allowed in addition."
No arguments are needed, but the compiler requires that I put in an argument. Is this correct?
I seem to recall that when I programmed professionally (in the 1970's), I didn't use FUNCTIONs. I only used SUBROUTINEs and passed the results as arguments.
Dan |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7934 Location: Salford, UK
|
Posted: Sat Oct 21, 2017 9:38 pm Post subject: |
|
|
No. A function can have no arguments. You can post the code that fails if you wish. |
|
Back to top |
|
|
DanRRight
Joined: 10 Mar 2008 Posts: 2828 Location: South Pole, Antarctica
|
Posted: Sun Oct 22, 2017 10:44 am Post subject: |
|
|
Dan,
When defining a function you need to add parentheses even with no arguments.
When using function - parentheses are omittable.
This is counterintuitive but that's how it is in Fortran |
|
Back to top |
|
|
kaliuzhkin
Joined: 17 Sep 2012 Posts: 33
|
Posted: Wed Oct 25, 2017 8:58 pm Post subject: lack of argument |
|
|
Paul: Here is the main program, which calls Function TwoDice:
WINAPP !for CLEARWIN
PROGRAM Main
USE CLRWIN$
!
! Fortran 95, Martin Counihan
! Section 7.2, Exercises 7.A, page 114
! Exercise 7.A10, a/k/a 7.Aa.
! This is file Ex.Aa_tst_Main.f95.
! This version tests not having any arguments.
!
! "Using RANDOM [rather, RANDOM_NUMBER], write an integer function
! that will simulate the throw of two dice, adding their results. If
! a double is thrown, an extra throw is allowed in addition."
!
! The function TwoDice returns a scalar, giving the total of the
! throw on two dice. This main program determines if doubles were thrown.
! I suspect that the function must have an argument.
!
! (This version doesn't have any arguments.)
!
IMPLICIT NONE
INTEGER, EXTERNAL:: TwoDice
INTEGER:: Tot, Total
!
MainLoop: DO !We will repeat this process indefinitely
Tot = TwoDice !Call the function - roll the dice
Total = ABS(Tot)
WRITE(*,*) "The total roll of the dice is: ", Total
Doubles: IF (Tot.LT.0) THEN
CYCLE MainLoop !Doubles, roll again
ELSE IF (Tot.GT.0) THEN Doubles
PAUSE !Not doubles, await operator response
CYCLE MainLoop
ELSE Doubles
STOP "How did we get here?"
END IF Doubles
END DO MainLoop
!
END PROGRAM Main
Compiling it in Plato, �Debug Win32� yields the following error in Errorlog:
C:\Kalish_data\FORTRAN source\95\Fortran 95 Counihan\ch07p114\Ex7.Aa_tst_Main.F95(26) : error 1168 - TWODICE is a routine name, and cannot be used in this context
and in Ex7.Aa_tst_Main.ERR:
C:\Kalish_data\FORTRAN source\95\Fortran 95
Counihan\ch07p114\Ex7.Aa_tst_Main.F95(26) : error 1168 - TWODICE is a
routine name, and cannot be used in this context
The same error results from compiling with ftn95.exe in command prompt.
Note that I use the following compilation options, specified in ftn95.cfg:
/COLOUR /DELETE_OBJ_ON_ERROR /DUMP /ERROR_NUMBERS /ERRORLOG /-LINK /LIST /MAP /MINIMISE_REBUILD /-NO_BANNER /NO_TRUNCATE /NON_STANDARD /PERSIST /SINGLE_THREADED /STATISTICS /UNDERFLOW /UNLIMITED_ERRORS /VS7 /WINDOWS /WRAP /XREF /CHECK /CHECKMATE /FULL_UNDEF /FULL_DEBUG
Compiling the function went smoothly, so I didn�t include the function source code.
Everything goes fine if both the main program and the function include an argument.
DanRR -- I'll try what you suggested.
Dan |
|
Back to top |
|
|
LitusSaxonicum
Joined: 23 Aug 2005 Posts: 2390 Location: Yateley, Hants, UK
|
Posted: Wed Oct 25, 2017 10:12 pm Post subject: |
|
|
The function isn't EXTERNAL, for a start, and when I produce a function and remove the EXTERNAL attribute, that error goes away. also add brackets to the call to get rid of the warning.
Code: | WINAPP !for CLEARWIN
PROGRAM Main
USE CLRWIN$
IMPLICIT NONE
INTEGER TwoDice
INTEGER:: Tot, Total
MainLoop: DO !We will repeat this process indefinitely
Tot = TwoDice() !Call the function - roll the dice
Total = ABS(Tot)
WRITE(*,*) "The total roll of the dice is: ", Total
Doubles: IF (Tot.LT.0) THEN
CYCLE MainLoop !Doubles, roll again
ELSE IF (Tot.GT.0) THEN Doubles
PAUSE !Not doubles, await operator response
CYCLE MainLoop
ELSE Doubles
STOP "How did we get here?"
END IF Doubles
END DO MainLoop
END PROGRAM Main
INTEGER FUNCTION TwoDice()
TwoDice = 1
END |
|
|
Back to top |
|
|
DanRRight
Joined: 10 Mar 2008 Posts: 2828 Location: South Pole, Antarctica
|
Posted: Thu Oct 26, 2017 1:16 am Post subject: |
|
|
Eddie, compiles fine with or without EXTERNL. It is the parethesis what was the issue.
And of course way too laconic error messages completely unacceptable for the novices. The guy is trying to run his first program ***for weeks***, isn't this a proof that compiler developers have to change? It is hard to express how I hated those compiler messages when I was just learning English and Fortran. And I started to hate them again as the difficulty to debug larger and larger codes grow exponentially.
Yesterday I also got one of such "elitist" messages: "Unknown variable", "This variable is illegal in this context" or something like that and was scratching my head for an hour trying to understand how I have to proceed to find a needle in the hive. I see the variable, debugger sees the variable, compiler did not complain about this variable, it was explicitly declared as usual so even John Campbell will not shirtfront me (like former Australian PM Tony Abbott tried with Putin) with his 'implicit none', still I got Access Violation and when debugged and hovered on variable with the mouse in SDBG the bubble message popped "Unknown Variable" )))
Found the error literally by mistake. In another place similar variable was called as if it was a function. Was it hard to add why compiler considered this variable as an illegal or unknown? Not enough RAM or harddrive space like in 1980th?
For novices and i'd say even for everyone besides probably total 1-2 people the more verbose error messages with the suggestions covering how typically such errors appear is what this compiler needs.
Last edited by DanRRight on Thu Oct 26, 2017 4:24 am; edited 1 time in total |
|
Back to top |
|
|
JohnCampbell
Joined: 16 Feb 2006 Posts: 2560 Location: Sydney
|
Posted: Thu Oct 26, 2017 2:55 am Post subject: |
|
|
The following is an example of using a FUNCTION without any arguments.
The use of EXTERNAL is optional.
Most timing functions do not require an option, or where the inputs are provided via COMMON or MODULE.
Arguments were once required, so "old" Fortran looks better without () call list.
Dan, There are few similarities between myself and Tony Abbott !!
John
Code: | ! example of function without argument
!
character time_string*11, ans*11
external time_string ! external is optional
!
ans = time_string ()
write (*,*) 'time : ',ans
end
character*11 function time_string ()
!
! returns the time in the form hh:mm:ss pm
!
CHARACTER CBUF*11, am_pm*3
integer*4 ia(8), hour
!
call Date_and_Time (VALUES=ia)
!
hour = ia(5)
am_pm = ' am'
IF (hour >= 12) am_pm = ' pm'
IF (hour > 12) hour = hour-12
IF (hour == 0) hour = 12
!
WRITE (CBUF,1011) hour, ia(6), ia(7), am_pm
!
time_string = CBUF
!
RETURN
1011 FORMAT (I2,':',I2.2,':',I2.2,A3)
END function time_string |
|
|
Back to top |
|
|
LitusSaxonicum
Joined: 23 Aug 2005 Posts: 2390 Location: Yateley, Hants, UK
|
Posted: Thu Oct 26, 2017 9:58 am Post subject: |
|
|
Dan, John, I agree that the parentheses are the issue, but I reported what I found. EXTERNAL is indeed not the problem, but without it, the original error message goes away. If FTN95 reported warnings for everything, it would include warning No. XYZ1234 'EXTERNAL specified when FUNCTION name not used in a subprogram call'. FTN95 has several of these 'don't matter' things, like if a subprogram expects LOGICAL you can supply 0 or 1 or an integer variable.These things may matter decades hence.
Dan, I like the verb 'to shirtfront', but the needle is lost in a haystack, not a hive. One hopes not to find needles these days!
Eddie |
|
Back to top |
|
|
DanRRight
Joined: 10 Mar 2008 Posts: 2828 Location: South Pole, Antarctica
|
Posted: Fri Oct 27, 2017 3:12 am Post subject: |
|
|
Eddie, looking for the needle in the bee hive would better resemble my everyday troubles with English and Fortran languages . As to diagnostics, does your compiler give the error message on EXTERNAL and warning on absent () ? |
|
Back to top |
|
|
DanRRight
Joined: 10 Mar 2008 Posts: 2828 Location: South Pole, Antarctica
|
Posted: Fri Oct 27, 2017 9:36 am Post subject: Re: |
|
|
JohnCampbell wrote: | Dan, There are few similarities between myself and Tony Abbott !!John |
I was puzzling all days what that means. You'd for sure punch Putin ? |
|
Back to top |
|
|
LitusSaxonicum
Joined: 23 Aug 2005 Posts: 2390 Location: Yateley, Hants, UK
|
Posted: Fri Oct 27, 2017 11:27 am Post subject: |
|
|
Dan,
When I'm not using FTN95, I use the Holy_Grail compiler from Fantasy Land computer services, Camelot, near Stonehenge. It has the wonderful facility to compile what you intended, rather than what you wrote, and if you use the /c (change) switch, it changes the source code to suit. Moreover, as it was developed some time ago, it has none of the newfangled stuff, most of which is already there but in a different guise. It can detect common typing errors, accidental deletion of characters and so on, and with the /i (imagine) switch, it does such routine things as matching mismatched brackets, quotes, function and subroutine declarations and calls, and so on. Executable codes run at least 100x quicker than the fastest of the other compilers - and there are never any run time errors. It enforces strict compliance to the Fortran standard in use when it was developed (Merlin could only foresee 77) - unless you intended something else and it does that instead (with the /u for understood switch, of course). A final advantage - it stamps out devilry! (With the /e for exorcism switch).
Unfortunately, it doesn't support Clearwin+ and has no graphics - so for many practical purposes it is useless, and is why I use FTN95 for everything that matters.
Oh Drat! It was a serious question. Yes, when I knock out EXTERNAL the error message goes, leaving just the warning, which is removed when () are added in.
Eddie |
|
Back to top |
|
|
JohnCampbell
Joined: 16 Feb 2006 Posts: 2560 Location: Sydney
|
Posted: Fri Oct 27, 2017 12:38 pm Post subject: |
|
|
Dan,
About the only similarity between myself and Tony Abbot is we have been members of Queenscliff surf lifesaving club.
I will stick to Fortran please.
John |
|
Back to top |
|
|
DanRRight
Joined: 10 Mar 2008 Posts: 2828 Location: South Pole, Antarctica
|
Posted: Fri Oct 27, 2017 12:47 pm Post subject: |
|
|
Eddie, I did not ask without the reason because the warning when you add external rise the suspicion that i am not alone influenced by the devilry if you confirm that your compiler is 8.10.
John, agree, let's return to Fortran:
Code: |
!
! I do not know how media covered this in Australia,
! but it was big fun in the rest of the world to wait
! fistfight between PM and Putin and even bigger laugh
! when Putin came and nothing happened.
! PM's days after that were counted.
! |
|
|
Back to top |
|
|
kaliuzhkin
Joined: 17 Sep 2012 Posts: 33
|
Posted: Thu Nov 02, 2017 7:52 pm Post subject: |
|
|
Still no good. It doesn�t seem to matter how I phrase the FUNCTION statement: FUNCTION TwoDice() or FUNCTION TwoDice give the same results. The problem is the main program. It never seems to call the function.
Compiling the main program yields the above-mentioned error about an undefined variable, array element or function result. If I compile with the /-FULL_UNDEF option, compilation gives a warning �C:\Kalish_data\FORTRAN source\95\Fortran 95 Counihan\ch07p114\Ex7.Aa_test_Main.F95(31) : warning 298 - Variable TWODICE has been used without being given an initial value�. The routines can be SLINKed and executed, but the main program never seems to call the function. None of the WRITE statements in the function are executed, and the value �returned� is -128, which is the value of an undefined INTEGER KIND=1.
Following is the .XRF file for the main routine:
Silverfrost FTN95 Ver 8.10.0 Cross reference information for Ex7.Aa_test_Main.F95 Fri Oct 27 15:45:01 2017
Line numbers followed by ~ refer to include files.
Line numbers followed by * represent variable assignments and label definitions.
Generating information for SUBROUTINE MAIN
REAL, PURE, ELEMENTAL :: FUNCTION ABS
45
SUBROUTINE MAIN
INTEGER :: FUNCTION SELECTED_INT_KIND
32
INTEGER(KIND=1) :: TOT
32, 34*, 35, 44, 45, 47, 49
INTEGER(KIND=1) :: TOTAL
32, 45*, 46
INTEGER(KIND=1) :: TWODICE
32, 34
The .MAP file for the main routine:
Linker Map of C:\Kalish_data\FORTRAN source\95\Fortran 95 Counihan\ch07p114\Ex7.Aa_test_Main.EXE Fri Oct 27 15:45:02 2017
Image base = 400000 Image align = 1000 File align = 200
Stack = 3200000 Heap = 100000
Entry point _SALFStartup at 00401220
00400000 header Linker defined
Address Name File in which defined
Code
00401000 MAIN C:\Kalish_data\FORTRAN source\95\Fortran 95 Counihan\ch07p114\lgotemp@.obj
(C:\KALISH_DATA\FORTRAN SOURCE\95\FORTRAN 95 COUNIHAN\CH07P114\EX7.AA_TEST_MAIN.F95)
00401000 __clearwin C:\Kalish_data\FORTRAN source\95\Fortran 95 Counihan\ch07p114\lgotemp@.obj
(C:\KALISH_DATA\FORTRAN SOURCE\95\FORTRAN 95 COUNIHAN\CH07P114\EX7.AA_TEST_MAIN.F95)
00401000 main C:\Kalish_data\FORTRAN source\95\Fortran 95 Counihan\ch07p114\lgotemp@.obj
(C:\KALISH_DATA\FORTRAN SOURCE\95\FORTRAN 95 COUNIHAN\CH07P114\EX7.AA_TEST_MAIN.F95)
00401220 SALFStartup C:\Program Files (x86)\Silverfrost\FTN95ver8.10\salflibc.lib (/0 )
(\cpplib\nt_dll\salfstar.obj)
0040122a SALFStart C:\Program Files (x86)\Silverfrost\FTN95ver8.10\salflibc.lib (/0 )
(\cpplib\nt_dll\salfstar.obj)
00401940 __undefined_function C:\Program Files (x86)\Silverfrost\FTN95ver8.10\salflibc.lib (salflibc.dll/ )
00401950 WSF2# C:\Program Files (x86)\Silverfrost\FTN95ver8.10\salflibc.lib (salflibc.dll/ )
00401960 WSF1## C:\Program Files (x86)\Silverfrost\FTN95ver8.10\salflibc.lib (salflibc.dll/ )
00401970 STOP# C:\Program Files (x86)\Silverfrost\FTN95ver8.10\salflibc.lib (salflibc.dll/ )
00401980 __CCOPY_U C:\Program Files (x86)\Silverfrost\FTN95ver8.10\salflibc.lib (salflibc.dll/ )
00401990 __set_underflow_flag C:\Program Files (x86)\Silverfrost\FTN95ver8.10\salflibc.l |
|
Back to top |
|
|
JohnCampbell
Joined: 16 Feb 2006 Posts: 2560 Location: Sydney
|
Posted: Fri Nov 03, 2017 12:20 am Post subject: |
|
|
Declaring a function without any arguments should not be a issue.
You must be doing something else unusual.
Try the following change to your posted code: Code: | WINAPP !for CLEARWIN
PROGRAM Main
USE CLRWIN$
!
! Fortran 95, Martin Counihan
! Section 7.2, Exercises 7.A, page 114
! Exercise 7.A10, a/k/a 7.Aa.
! This is file Ex.Aa_tst_Main.f95.
! This version tests not having any arguments.
!
! "Using RANDOM [rather, RANDOM_NUMBER], write an integer function
! that will simulate the throw of two dice, adding their results. If
! a double is thrown, an extra throw is allowed in addition."
!
! The function TwoDice returns a scalar, giving the total of the
! throw on two dice. This main program determines if doubles were thrown.
! I suspect that the function must have an argument.
!
! (This version doesn't have any arguments.)
!
IMPLICIT NONE
INTEGER, EXTERNAL:: TwoDice
INTEGER:: Tot, Total
!
MainLoop: DO !We will repeat this process indefinitely
Tot = TwoDice () !Call the function - roll the dice
Total = ABS(Tot)
WRITE (*,*) "The total roll of the dice is: ", Total
Doubles: IF (Tot.LT.0) THEN
CYCLE MainLoop !Doubles, roll again
ELSE IF (Tot.GT.0) THEN Doubles
PAUSE !Not doubles, await operator response
CYCLE MainLoop
ELSE Doubles
STOP "How did we get here?"
END IF Doubles
END DO MainLoop
!
END PROGRAM Main
integer function TwoDice ()
integer i
integer, external :: RollDice
TwoDice = 0
do i = 1,2
TwoDice = TwoDice + RollDice ()
end do
end function TwoDice
integer function RollDice ()
real :: x
call random_number (x)
RollDice = (int(x*6.) + 1)
end function RollDice |
My function only reports sum of rolling 2 dice, not doubles or other options ? |
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|