What is opposite of ExtractRelativePath in Pascal? - freepascal

I often use ExtractRelativePath to get the relative path between two path. But i cannot see any function opposite to it. This is an example from freepascal.org:
Uses sysutils;
Procedure Testit (FromDir,ToDir : String);
begin
Write ('From "',FromDir,'" to "',ToDir,'" via "');
Writeln (ExtractRelativePath(FromDir,ToDir),'"');
end;
Begin
Testit ('/pp/src/compiler','/pp/bin/win32/ppc386');
Testit ('/pp/bin/win32/ppc386','/pp/src/compiler');
Testit ('e:/pp/bin/win32/ppc386','d:/pp/src/compiler');
Testit ('e:\pp\bin\win32\ppc386','d:\pp\src\compiler');
End.
Output of this program
From "/pp/src/compiler" to "/pp/bin/win32/ppc386" via "../bin/win32/ppc386"
From "/pp/bin/win32/ppc386" to "/pp/src/compiler" via "../../src/compiler"
From "e:/pp/bin/win32/ppc386" to "d:/pp/src/compiler" via "../../src/compiler"
From "e:\pp\bin\win32\ppc386" to "d:\pp\src\compiler" via "../../src/compiler"
I need a function F to perform reverse action of ExtractRelativePath, for example:
F('/pp/src/compiler', '../bin/win32/ppc386') return '/pp/bin/win32/ppc386'.
Do you know any function like this? Thank you in advance.

Yes, sure. http://docwiki.embarcadero.com/Libraries/XE5/en/System.IOUtils.TPath.Combine
System.IOUtils.TPath.Combine
class function Combine(const Path1, Path2: string): string; inline; static;
Description
Combines two paths strings.
Call Combine to obtain a new combined path from two distinct paths. If
the second path is absolute, Combine returns it directly; otherwise
Combine returns the first path concatenated with the second one.
Above was written when the question was tagged by delphi
Now, for FPC simple scan through SysUtils sources lands you onto
c:\codetyphon\fpcsrc\rtl\objpas\sysutils\finah.inc
Which has
function ConcatPaths(const Paths: array of String): String;
Which is documented at
http://www.freepascal.org/docs-html/rtl/sysutils/concatpaths.html
ConcatPaths
Concatenate an array of paths to form a single path
Declaration
Source position: finah.inc line 42
function ConcatPaths( const Paths: array of ):;
Description
ConcatPaths will concatenate the different path components in Paths to
a single path. It will insert directory separators between the various
components of the path as needed. No directory separators will be
added to the beginning or the end of the path, and none will be taken
away.
Example
program ex96;
{ This program demonstrates the Concatpaths function }
uses sysutils;
begin
// will write /this/path/more/levels/
Writeln(ConcatPaths(['/this/','path','more/levels/']));
// will write this/path/more/levels/
Writeln(ConcatPaths(['this/','path','more/levels/']));
// will write this/path/more/levels
Writeln(ConcatPaths(['this/','path','more/levels']));
end.

Related

Lua - Match pattern for CSV import to array, that factors in empty values (two commas next to each other)

I have been using the following Lua code for a while to do simply csv to array conversions, but everything previously had a value in every column, but this time on a csv formatted bank statement there are empty values, which this does not handle.
Here’s an example csv, with debit and credits.
Transaction Date,Transaction Type,Sort Code,Account Number,Transaction Description,Debit Amount,Credit Amount,Balance
05/04/2022,DD,'11-70-79,6033606,Refund,,10.00,159.57
05/04/2022,DEB,'11-70-79,6033606,Henry Ltd,30.00,,149.57
05/04/2022,SO,'11-70-79,6033606,NEIL PARKS,20.00,,179.57
01/04/2022,FPO,'11-70-79,6033606,MORTON GREEN,336.00,,199.57
01/04/2022,DD,'11-70-79,6033606,WORK SALARY,,100.00,435.57
01/04/2022,DD,'11-70-79,6033606,MERE BC,183.63,,535.57
01/04/2022,DD,'11-70-79,6033606,ABC LIFE,54.39,,719.20
I’ve tried different patterns (https://www.lua.org/pil/20.2.html), but none seem to work, I’m beginning to think I can’t fix this via the pattern as it’ll break how it works for the rest? I appreciate it if anyone can share how they would approach this…
local csvfilename = "/mnt/nas/Fireflyiii.csv"
local MATCH_PATTERN = "[^,]+"
local function create_array_from_file(csvfilename)
local file = assert(io.open(csvfilename, "r"))
local arr = {}
for line in file:lines() do
local row = {}
for match in string.gmatch(line, MATCH_PATTERN) do
table.insert(row, match)
end
table.insert(arr, row)
end
return arr
end

lua not modifying function arguments

I've been learning lua and can't seem to make a simple implementation of this binary tree work...
function createTree(tree, max)
if max > 0 then
tree = {data = max, left = {}, right = {}}
createTree(tree.left, max - 1)
createTree(tree.right, max - 1)
end
end
function printTree(tree)
if tree then
print(tree.data)
printTree(tree.left)
printTree(tree.right)
end
end
tree = {}
createTree(tree, 3)
printTree(tree)
the program just returns nil after execution. I've searched around the web to understand how argument passing works in lua (if it is by reference or by value) and found out that some types are passed by reference (like tables and functions) while others by value. Still, I made the global variable "tree" a table before passing it to the "createTree" function, and I even initialized "left" and "right" to be empty tables inside of "createTree" for the same purpose. What am I doing wrong?
It is probably necessary to initialize not by a new table, but only to set its values.
function createTree(tree, max)
if max > 0 then
tree.data = max
tree.left = {}
tree.right = {}
createTree(tree.left, max - 1)
createTree(tree.right, max - 1)
end
end
in Lua, arguments are passed by value. Assigning to an argument does not change the original variable.
Try this:
function createTree(max)
if max == 0 then
return nil
else
return {data = max, left = createTree(max-1), right = createTree(max-1)}
end
end
It is safe to think that for the most of the cases lua passes arguments by value. But for any object other than a number (numbers aren't objects actually), the "value" is actually a pointer to the said object.
When you do something like a={1,2,3} or b="asda" the values on the right are allocated somewhere dynamically, and a and b only get addresses of those. Thus, when you pass a to the function fun(a), the pointer is copied to a new variable inside function, but the a itself is unaffected:
function fun(p)
--p stores address of the same object, but `p` is not `a`
p[1]=3--by using the address you can
p[4]=1--alter the contents of the object
p[2]=nil--this will be seen outside
q={}
p={}--here you assign address of another object to the pointer
p=q--(here too)
end
Functions are also represented by pointers to them, you can use debug library to tinker with function object (change upvalues for example), this may affect how function executes, but, once again, you can not change where external references are pointing.
Strings are immutable objects, you can pass them around, there is a library that does stuff to them, but all the functions in that library return new string. So once, again external variable b from b="asda" would not be affected if you tried to do something with "asda" string inside the function.

Inno Setup - Defining a default path inside [code]

I'm trying to read the Windows Registry so my app updates can retrieve the previously saved instalation path as its DefaultDirName.
I've read somewhere that I should call a function, like:
DefaultDirName="{code:GetPath}"
The problem is that I need to define a default path, in case the function does not find a previous one. For instance, 'C:\MyPath'. So I did this:
[Code]
function GetPath(Value: String): String;
var
OrigPath: string;
begin
Result := '{sd}\MyPath';
if RegQueryStringValue(HKCU, 'Software\MyApp', 'PathExec', OrigPath) then
Result := OrigPath;
end;
That is not working. When I run the setup, at the destination dir dialog I'm getting literally "C:\PathOfMySetup\{sd}\MyPath", not "C:\MyPath".
What should I write at that first "Result := " line in order to "MyPath" be created at the System Drive?
Thanks.
The constants in Pascal Script are not magically expanded. You have to expand them explicitly using the ExpandConstant function:
Result := ExpandConstant('{sd}\MyPath');

Ti-basic passing function as an argument to another function

In Matlab you can declare an anonymous function and pass it to another function.
[y] = someFunction(#(x) x.^2 , [a bunch of numbers]);
I'd like to do something similar on my TI-89 calculator. I have a function that takes a "math-function" as one of its arguments and I'm trying to do it like this:
myfunction(3/x,1,2)
and my function looks something like this:
myfunction(f,xl,xu)
Func
local a,b
f(xl)→a
f(xu)→b
Return [a,b]
EndFunc
I know I can input my functions in the "y=" editor and then access them inside the function but I would really like to be able to input the math-function directly as an argument. How can I do this?
The builtin expr function in TI-BASIC can be used to turn a string into an expression. Here's how to implement your function this way:
myfunction(f,xl,xu)
Func
Local a,b,x
xl→x
expr(f)→a
xu→x
expr(f)→b
Return [a,b]
EndFunc
The call to your function will be myfunction("3/x",1,2). Be sure to enclose the definition of f in double quotes so it is treated as a string.
"TI-89 BASIC does not have first-class functions; while function definitions as stored in variables are fully dynamic, it is not possible to extract a function value from a variable rather than calling it. In this case, we use the indirection operator #, which takes a string and returns the value of the named variable, to use the name of the function as something to be passed."
http://rosettacode.org/wiki/Higher-order_functions#TI-89_BASIC

Lua - Execute a Function Stored in a Table

I was able to store functions into a table. But now I have no idea of how to invoke them. The final table will have about 100 calls, so if possible, I'd like to invoke them as if in a foreach loop. Thanks!
Here is how the table was defined:
game_level_hints = game_level_hints or {}
game_level_hints.levels = {}
game_level_hints.levels["level0"] = function()
return
{
[on_scene("scene0")] =
{
talk("hint0"),
talk("hint1"),
talk("hint2")
},
[on_scene("scene1")] =
{
talk("hint0"),
talk("hint1"),
talk("hint2")
}
}
end
Aaand the function definitions:
function on_scene(sceneId)
-- some code
return sceneId
end
function talk(areaId)
-- some code
return areaId
end
EDIT:
I modified the functions so they'll have a little more context. Basically, they return strings now. And what I was hoping to happen is that at then end of invoking the functions, I'll have a table (ideally the levels table) containing all these strings.
Short answer: to call a function (reference) stored in an array, you just add (parameters), as you'd normally do:
local function func(a,b,c) return a,b,c end
local a = {myfunc = func}
print(a.myfunc(3,4,5)) -- prints 3,4,5
In fact, you can simplify this to
local a = {myfunc = function(a,b,c) return a,b,c end}
print(a.myfunc(3,4,5)) -- prints 3,4,5
Long answer: You don't describe what your expected results are, but what you wrote is likely not to do what you expect it to do. Take this fragment:
game_level_hints.levels["level0"] = function()
return
{
[on_scene("scene0")] =
{
talk("hint0"),
}
}
end
[This paragraph no longer applies after the question has been updated] You reference on_scene and talk functions, but you don't "store" those functions in the table (since you explicitly referenced them in your question, I presume the question is about these functions). You actually call these functions and store the values they return (they both return nil), so when this fragment is executed, you get "table index is nil" error as you are trying to store nil using nil as the index.
If you want to call the function you stored in game_level_hints.levels["level0"], you just do game_level_hints.levels["level0"]()
Using what you guys answered and commented, I was able to come up with the following code as a solution:
asd = game_level_hints.levels["level0"]()
Now, asd contains the area strings I need. Although ideally, I intended to be able to access the data like:
asd[1][1]
accessing it like:
asd["scene0"][1]
to retrieve the area data would suffice. I'll just have to work around the keys.
Thanks, guys.
It's not really clear what you're trying to do. Inside your anonymous function, you're returning a table that uses on_scene's return value as keys. But your on_scene doesn't return anything. Same thing for talk.
I'm going to assume that you wanted on_scene and talk to get called when invoking each levels in your game_level_hints table.
If so, this is how you can do it:
local maxlevel = 99
for i = 0, maxlevel do
game_level_hints.levels["level" .. i] = function()
on_scene("scene" .. i)
talk("hint" .. i)
end
end
-- ...
for levelname, levelfunc in pairs(game_level_hints.levels) do
levelfunc()
end