Tiny Core Extensions > TCE Tips & Tricks

search tcz/src source for build scripts (rsync)

<< < (2/3) > >>

mocore:
hi rich
 ;) not exactly , but i guess now we are both in the same boat so to speak
hopefully any one interested in running it can make any modifications after they copy or past it


reminds me of  https://en.wikipedia.org/wiki/Worse_is_better

but also ( as i have read a few scripts u posted hear )
make me wander if you have some policy/reason to avoid or just aversion to functions  ;)


Rich:
Hi mocore
Or maybe I misunderstood how you wanted it changed.
If you PM me how you want it to look, I'll adjust the post
accordingly.

mocore:

--- Code: ---find_src() {

 search_string=${1-w3m} # eg

 def_arch=${2-x86} # x86_64 or x86

 def_path="${tc_path-/*.x/x86/tcz/src/}"

 rsync -R --list-only repo.tinycorelinux.net::tc"${def_path}" | grep "$search_string"

 # tce-load -iwl rsync
 }
--- End code ---

Rich:
Hi mocore

--- Quote from: mocore on September 23, 2024, 09:39:41 AM --- ... but also ( as i have read a few scripts u posted hear )
make me wander if you have some policy/reason to avoid or just aversion to functions  ;)
--- End quote ---
I do not avoid or have an aversion to functions. I do try to be aware
of the impact they may have.

1. Functions are good.   They provide consistency and can make code easier to follow.
2. Functions are bad.    Making functions out of every little bit of code repetition can
                          leave you lost trying to follow a maze of functions.
3. Functions hurt speed. If your function returns a value to your variable, the impact
                          can become significant if it looks like this: Var=$(MyFunction).

I'd like to address item 3.


--- Code: ---#!/bin/sh

#: Calculate elapsed time.
#: Millisecond resolution If GNU date is present, otherwise seconds only.
GetET1(){ ET1=$(date +%s.%3N); ET1=${ET1%.%3N}; }
GetET2(){ ET2=$(date +%s.%3N); ET2=${ET2%.%3N}; }
CalcET(){ calc $ET2-$ET1; }


# --------------------------------------------------------------- #
# Checks that all chars are digits, and that digits are present.
IsInteger()
{
# Empty string is not an integer.
        # If we delete all of the digits, that should leave an empty string.
[ -z $1 ] || [ -n "${1//[0-9]/}" ] && echo "" && return

        # Valid integer.
        echo "$1"
return
}
# --------------------------------------------------------------- #



# --------------------------------------------------------------- #
# Checks that all chars are digits, and that digits are present.
IsIntegerByRef()
{
        # $1=Name of variable to place the result in.
        # $2=Number to validate.

local __IntVar=$1
local __Int2Test=$2

# Empty string is not an integer.
        # If we delete all of the digits, that should leave an empty string.
[ -z $2 ] || [ -n "${2//[0-9]/}" ] && __Int2Test=""

eval $__IntVar="'$__Int2Test'"
}
# --------------------------------------------------------------- #



#: --------------------------------------------------------------- #
#: Fixed point division. Input positive integers only, no zeros allowed.
#: Usage: Divide $Dividend $Divisor
Divide()
{
# Vars will either be an integer or empty from IsInteger.
local Dividend=$(IsInteger $1)
local Divisor=$(IsInteger $2)
# local Dividend=$1
# local Divisor=$2
# Number of decimal places desired.
# We increases decimal places by 1 to allow rounding.
local DPcount=$(($DPdefault + 1))
local Quotient
# Leading zero causes Decimal to be treated as octal. We deal
# with this by padding with a leadin one. Doubles as carry
# flag when rounding by incrementing to two.
local Decimal=1
local Zeros=".00000000"

# 2 integers are required.
[ -z $Dividend ] && echo "" && return
[ -z $Divisor ] && echo "" && return

# Dividing by zero not allowed.
[ $Divisor -eq 0 ] && echo "" && return
# Dividing into zero equals zero plus default decimal places..
if [ $Dividend -eq 0 ]
then
[ $DPcount -gt 0 ] && Decimal="${Zeros:0:$DPcount}"
printf "0%s\n" $Decimal
return
fi

# First calculate the integer portion.
Quotient=$(($Dividend / $Divisor))

# Calculate the remainder to the requested number of decimal places.
while [ $DPcount -gt 0 ]
do
Dividend=$((($Dividend % $Divisor) * 10))
Decimal="$Decimal$(($Dividend / $Divisor))"
DPcount=$(($DPcount - 1))
done

# Perform rounding.
Decimal=$(($Decimal + 5))
# Remove the extra decimal place we added by removing the last digit.
Decimal=${Decimal%[0-9]}

# If the leading digit equals 2, rounding caused a carry.
[ ${Decimal:0:1} -eq 2 ] && Quotient=$(($Quotient + 1))
# Remove the carry digit (MSD) from the decimal portion.
Decimal=${Decimal:1}

printf "%s.%s\n" $Quotient $Decimal
}
# --------------------------------------------------------------- #


#: --------------------------------------------------------------- #
#: Fixed point division. Input positive integers only, no zeros allowed.
#: Usage: Divide $Dividend $Divisor
DivideNoFunc()
{
# Vars will either be an integer or empty from IsInteger.
# local Dividend=$(IsInteger $1)
# local Divisor=$(IsInteger $2)
local Dividend
local Divisor
[ -z $1 ] || [ -n "${1//[0-9]/}" ] && Dividend="" || Dividend="$1"
[ -z $2 ] || [ -n "${2//[0-9]/}" ] && Divisor="" || Divisor="$2"
# Number of decimal places desired.
# We increases decimal places by 1 to allow rounding.
local DPcount=$(($DPdefault + 1))
local Quotient
# Leading zero causes Decimal to be treated as octal. We deal
# with this by padding with a leadin one. Doubles as carry
# flag when rounding by incrementing to two.
local Decimal=1
local Zeros=".00000000"

# 2 integers are required.
[ -z $Dividend ] && echo "" && return
[ -z $Divisor ] && echo "" && return

# Dividing by zero not allowed.
[ $Divisor -eq 0 ] && echo "" && return
# Dividing into zero equals zero plus default decimal places..
if [ $Dividend -eq 0 ]
then
[ $DPcount -gt 0 ] && Decimal="${Zeros:0:$DPcount}"
printf "0%s\n" $Decimal
return
fi

# First calculate the integer portion.
Quotient=$(($Dividend / $Divisor))

# Calculate the remainder to the requested number of decimal places.
while [ $DPcount -gt 0 ]
do
Dividend=$((($Dividend % $Divisor) * 10))
Decimal="$Decimal$(($Dividend / $Divisor))"
DPcount=$(($DPcount - 1))
done

# Perform rounding.
Decimal=$(($Decimal + 5))
# Remove the extra decimal place we added by removing the last digit.
Decimal=${Decimal%[0-9]}

# If the leading digit equals 2, rounding caused a carry.
[ ${Decimal:0:1} -eq 2 ] && Quotient=$(($Quotient + 1))
# Remove the carry digit (MSD) from the decimal portion.
Decimal=${Decimal:1}

printf "%s.%s\n" $Quotient $Decimal
}
# --------------------------------------------------------------- #


#: --------------------------------------------------------------- #
#: Fixed point division. Input positive integers only, no zeros allowed.
#: Usage: Divide $Dividend $Divisor
DivideByRef()
{
# Vars will either be an integer or empty from IsInteger.
# local Dividend=$(IsInteger $1)
# local Divisor=$(IsInteger $2)
local Dividend
local Divisor
IsIntegerByRef "Dividend" "$1"
IsIntegerByRef "Divisor" "$2"
# Number of decimal places desired.
# We increases decimal places by 1 to allow rounding.
local DPcount=$(($DPdefault + 1))
local Quotient
# Leading zero causes Decimal to be treated as octal. We deal
# with this by padding with a leadin one. Doubles as carry
# flag when rounding by incrementing to two.
local Decimal=1
local Zeros=".00000000"

# 2 integers are required.
[ -z $Dividend ] && echo "" && return
[ -z $Divisor ] && echo "" && return

# Dividing by zero not allowed.
[ $Divisor -eq 0 ] && echo "" && return
# Dividing into zero equals zero plus default decimal places..
if [ $Dividend -eq 0 ]
then
[ $DPcount -gt 0 ] && Decimal="${Zeros:0:$DPcount}"
printf "0%s\n" $Decimal
return
fi

# First calculate the integer portion.
Quotient=$(($Dividend / $Divisor))

# Calculate the remainder to the requested number of decimal places.
while [ $DPcount -gt 0 ]
do
Dividend=$((($Dividend % $Divisor) * 10))
Decimal="$Decimal$(($Dividend / $Divisor))"
DPcount=$(($DPcount - 1))
done

# Perform rounding.
Decimal=$(($Decimal + 5))
# Remove the extra decimal place we added by removing the last digit.
Decimal=${Decimal%[0-9]}

# If the leading digit equals 2, rounding caused a carry.
[ ${Decimal:0:1} -eq 2 ] && Quotient=$(($Quotient + 1))
# Remove the carry digit (MSD) from the decimal portion.
Decimal=${Decimal:1}

printf "%s.%s\n" $Quotient $Decimal
}
# --------------------------------------------------------------- #

# Calculations are performed to DPdefault + 1 decimal places, and
# rounded to DPdefault decimal places.
DPdefault=8


echo
echo "Function (requires subshell) Divide 21053358 6701492 equals $(Divide 21053358 6701492)"
GetET1; for C in `seq 1 10000`; do Divide 21053358 6701492 > /dev/null; done; GetET2; echo "Elapsed time for 10,000 runs=$(CalcET) Secs."
echo
echo "No function (inline code) DivideNoFunc 21053358 6701492 equals $(DivideNoFunc 21053358 6701492)"
GetET1; for C in `seq 1 10000`; do DivideNoFunc 21053358 6701492 > /dev/null; done; GetET2; echo "Elapsed time for 10,000 runs=$(CalcET) Secs."
echo
echo "Function (indirect variable reference) DivideByRef 21053358 6701492 equals $(DivideByRef 21053358 6701492)"
GetET1; for C in `seq 1 10000`; do DivideByRef 21053358 6701492 > /dev/null; done; GetET2; echo "Elapsed time for 10,000 runs=$(CalcET) Secs."
echo
--- End code ---

The above contains 3 fixed point division functions.
They all use the same code to confirm they received valid integers.
The only difference is how data is exchanged with the validation code.

Divide() calls a function like this to update the variable:

--- Code: ---Dividend=$(IsInteger $1)
--- End code ---

DivideNoFunc() uses inline code like this to update the variable:

--- Code: ---[ -z $1 ] || [ -n "${1//[0-9]/}" ] && Dividend="" || Dividend="$1"
--- End code ---

DivideByRef() passes the name of the variable and the value to validate to a function:

--- Code: ---IsIntegerByRef "Dividend" "$1"
--- End code ---

The timing is for each version calculating pi to 9 decimal places and
rounding to 8 decimal places 10,000 times:

--- Code: ---tc@E310:~/Scripting/AddressParser$ ./Functions

Function (requires sub-shell) Divide 21053358 6701492 equals 3.14159265
Elapsed time for 10,000 runs=17.052 Secs.

No function (inline code) DivideNoFunc 21053358 6701492 equals 3.14159265
Elapsed time for 10,000 runs=4.866 Secs.

Function (indirect variable reference) DivideByRef 21053358 6701492 equals 3.14159265
Elapsed time for 10,000 runs=5.424 Secs.
--- End code ---

I suspect the function call in the first example starts a sub-shell which results
in a big timing hit.

The second version with inline code is fastest as expected.

The third version only has a 12% timing penalty.

A copy of the script is also attached.

mocore:
hi & thanks for the scripts !

i ask because a vaguely remember reading/hearing it mentioned something along the lines of
'functions are expensive' (afaik/r more historically older hardware made performance cost more apparent )


--- Quote from: Rich on January 01, 2025, 03:28:51 PM ---2. Functions are bad.    Making functions out of every little bit of code repetition can
                          leave you lost trying to follow a maze of functions.

--- End quote ---

its interesting that "debug-ability" of function use is considered down side

... imho if all the functions where in a pipeline and did not alter any shared environment 
it would be easy(er) to reason about them ( and there input / output)

wrt "debug-ability" the (apparent) lack of "good" books  on writing debuggers
was mentioned in  "Not on the shelves: what nonexistent books, tools, and courses can tell us about ourselves "

... if you happen to know any ?

wrt

--- Quote --- lost trying to  follow a maze of functions
--- End quote ---

i found my self  lost trying to  follow a maze of functions  the other day

my solution was to write another function  (like the captain in  peter pan??)
which was called at the start & end of the other function's
that stored

function name

count of function calls (start++ , end--)

 and a few other (seaming relevant info)

enough to (hopefully!) track  what calls what and  how deep the callers are nested

 and added this info to print to stderr/log 

 which appears to (more or less) work

 causing function's to leave a trail of crumbs to stdout !
 ... less lost , but also now debugging *another* function  :o

Navigation

[0] Message Index

[#] Next page

[*] Previous page

Go to full version