(b3) declaration must be at the first level...why?

not that it really matters, but i ran into an interesting error in b3:

i’m not sure why this declaration wound up inside of another structure, but it did. anyway, is this something new?

QodlyScript requires all variables to be declared.
Are you here in a method?

this is in a class function. you can see that this is a declaration. qs seems to be complaining that it is inside of another construct (in this case, inside of an if block in the weatherLocations function, in the weather demo). the declaration is there for a for loop that follows, iterating over the days of the forecast.
this complaint is new in b3, i think. i had not touched this code since b1, and i’m not even sure if i wrote it, since it’s been months since it was touched.
here’s the code, for reference. i marked the line with “xxx”.

exposed Function getWeatherDataWithCity(location:object) : object
	var prompt:string
	var url, timeResp, day, theTime : string
	var currentTemp, winddirection, windspeed, tempMax, tempMin, probabilityOfPrecip, uvIndex : variant
	var currentCode, code, viDay : integer
	var dateResp : date

	var url : string
	var request : 4D.HTTPRequest
	var col : Collection
	var weatherObject : object

	var myForm: 4d.WebForm
	myForm=webForm

	prompt="Loading "+location.city
	myForm.setWarning(prompt)

	//request=4D.HTTPRequest.new("https://api.open-meteo.com/v1/forecast?latitude="+ capital.CapitalLatitude + "&longitude=" + capital.CapitalLongitude + "&timezone=America/New_York&daily=temperature_2m_max&daily=temperature_2m_min&daily=weathercode&current_weather=true&forecast_days=6&temperature_unit=fahrenheit&windspeed_unit=mph&precipitation_unit=inch").wait()
	url="https://api.open-meteo.com/v1/forecast"+\
	"?latitude="+ string(location.latitude) +\
	"&longitude=" + string(location.longitude) +\
	"&current_weather=true"+\
	"&daily=weather_code,temperature_2m_max,temperature_2m_min,uv_index_max,rain_sum,snowfall_sum,precipitation_hours,precipitation_probability_max,wind_speed_10m_max,wind_gusts_10m_max,wind_direction_10m_dominant"+\
	"&temperature_unit=fahrenheit"+\
	"&wind_speed_unit=mph"+\
	"&precipitation_unit=inch"+\
	"&timezone=America%2FNew_York"
	//"&current_weather=true&daily=weathercode,temperature_2m_max,temperature_2m_min,uv_index_max,rain_sum,snowfall_sum,precipitation_hours,precipitation_probability_max,wind_speed_10m_max,wind_gusts_10m_max,wind_direction_10m_dominant&temperature_unit=fahrenheit&wind_speed_unit=mph&precipitation_unit=inch&timezone=America%2FNew_York"
	//"&timezone=America/New_York&daily=temperature_2m_max&daily=temperature_2m_min&daily=weathercode&current_weather=true&forecast_days=6&temperature_unit=fahrenheit&windspeed_unit=mph&precipitation_unit=inch"
	request=4D.HTTPRequest.new(url).wait()
	If (request.response.status==200)
  
  		weatherObject=newObject()
		
		theTime = substring(request.response.body.current_weather.time,12,5)
		currentTemp = request.response.body.current_weather.temperature
		currentCode = request.response.body.current_weather.weathercode
		winddirection = request.response.body.current_weather.winddirection
		windspeed = request.response.body.current_weather.windspeed

		weatherObject.current=newObject("theTime",theTime,"currentTemp",currentTemp,"currentPict",this.getWeatherPict(currentCode),"windDirection",winddirection,"windSpeed",windspeed)

		col=newCollection()
		var i : integer // xxx this is the line that triggers the complaint

		For (i,0,request.response.body.daily.temperature_2m_max.length-1)
			tempMax = request.response.body.daily.temperature_2m_max[i] || "Null"
			tempMin = request.response.body.daily.temperature_2m_min[i] || "Null"
			timeResp = request.response.body.daily.time[i] || "Null"
			probabilityOfPrecip = request.response.body.daily.precipitation_probability_max[i] || "Null"
			uvIndex = request.response.body.daily.uv_index_max[i] || "Null"
			code = request.response.body.daily.weather_code[i] || "Null"

			// UPDATE DATE FORMAT
			dateResp=date(replaceString(Substring(timeResp,5)+"/"+Substring(timeResp,0,4);"-";"/"))
			//"2023-05-02",
			//MMJJYY

			// GET WEEK DAY FROM DATE
			viDay =dayNumber(dateResp) ` viDay gets the current day number
			
			switch
				:(viDay ==1)
					day="Sunday"
				:(viDay ==2)
					day="Monday"
				:(viDay ==3)
					day="Tuesday"
				:(viDay ==4)
					day="Wednesday"
				:(viDay ==5)
					day="Thursday"
				:(viDay ==6)
					day="Friday"
				:(viDay ==7)
					day="Saturday"
 			end

			col.push(newObject("tempMax",tempMax,"tempMin",tempMin,"day",day,"pict",this.getWeatherPict(code),"probabilityOfPrecip",probabilityOfPrecip,"uvIndex",uvIndex))
			
		end

		weatherObject.forecast=col
		myForm.setMessage("Weather udpated.")
		return weatherObject

 	else 
  		// The code to handle errors.
 	end

I had the same issue so just moved the declaration but did wonder why.

QodlyScript requires variable declarations to be at first level in a class function.
Declaring a variable inside a if or for statement would be no more than aesthetic, as QodlyScript does not currently handle variable scope.

I guess you could avoid the declaration of the extra variables by putting them inside the if if the condition isn’t met, but always pretty easy to just declare them at the top level. Thanks.

omg b3 was sooooo long ago.
anyway, having just refactored a 4d project with direct typing, i repeatedly ran into a good reason for more flexibility: the length of a method or function. some functions and classes get to be pretty long. having declarations at the top and the first use of a variable a hundred or more lines later (sometimes because there are 20 lines of declarations) can force lots of scrolling, losing ones place when repeatedly scrolling back and forth, etc.
that obviously happens, more, earlier in a project, when code is being refactored…again…

stylistically, i’m more of a fan of having all the declarations at the top or at level 1 (as opposed to spreading them out, or having them inline), but there is a benefit to not having them all at level 1.

1 Like

We understand this.
We have variable scope in mind for QodlyScript, but still hesitating in implementing it :slight_smile:

imagine all the complaining from the purists, insisting that the only way is the declare every var + type every var
then, just for the lolz, make it happen