Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

If use sort_with_compare, it will report an error #20436

Closed
xiusin opened this issue Jan 8, 2024 · 11 comments · Fixed by #20485
Closed

If use sort_with_compare, it will report an error #20436

xiusin opened this issue Jan 8, 2024 · 11 comments · Fixed by #20485
Assignees
Labels
Bug This tag is applied to issues which reports bugs.

Comments

@xiusin
Copy link
Contributor

xiusin commented Jan 8, 2024

Describe the bug

pub fn (mut api App) api_account_position() vweb.Result {
    mut postions := []AccountPosition{} // some items

    for i, mut postion in postions {
		postion.recid = postion.inst_id
		if postion.mgn_ratio.f64() * 100 <= 300 {
			postion.w2ui.style = 'background-color: #f3d6e3'
		} else if postion.upl_ratio.f64() * 100 < -50 {
			postion.w2ui.style = 'background-color: rgb(242, 250, 140)'
		} else {
			mut ratio := 0
			if postion.lever.f64() >= 20 {
				ratio = 50
			} else if postion.lever.f64() >= 10 {
				ratio = 30
			} else if postion.lever.f64() >= 3 {
				ratio = 20
			}
			if postion.upl_ratio.f64() * 100 > ratio {
				postion.w2ui.style = 'background-color: #C2F5B4'
			}
		}
		postions[i] = postion
	}

	request := api.query['request'] or { '{}' }
	dto := json.decode(RequestDto, request) or { RequestDto{} }
      // If you use sort_with_compare, it will report an error on the last line
	postions.sort_with_compare(fn [dto] (a &AccountPosition, b &AccountPosition) int {
		if dto.sort.len == 0 {
			return 0
		}

		mut left := ''
		mut right := ''
		left, right = match dto.sort[0].field {
			'uplRatio' {
				a.upl_ratio, b.upl_ratio
			}
			'upl' {
				a.upl, b.upl
			}
			else {
				'', ''
			}
		}
		if left == right {
			return 0
		}

		if dto.sort[0].direction == 'desc' {
			return if left < right { -1 } else { 1 }
		} else {
			return if left > right { -1 } else { 1 }
		}
	})

	return api.json(postions) <- here 
}
image

It will work properly after the annotation sorting function is implemented

image

Is it a bug or my usage error? How can I fix this problem?

Reproduction Steps

--

Expected Behavior

success compile

Current Behavior

failed

Possible Solution

No response

Additional Information/Context

No response

V version

V 0.4.3 e2334d8

Environment details (OS name and version, etc.)

V full version: V 0.4.3 f705897.e2334d8
OS: macos, macOS, 13.5.1, 22G90
Processor: 8 cpus, 64bit, little endian, Intel(R) Core(TM) i5-8279U CPU @ 2.40GHz

getwd: /Users/xiusin/projects/
vexe: /opt/v/v
vexe mtime: 2024-01-05 10:50:47

vroot: OK, value: /opt/v
VMODULES: OK, value: /Users/xiusin/.vmodules
VTMP: OK, value: /tmp/v_501

Git version: git version 2.23.0
Git vroot status: weekly.2023.50-176-ge2334d8b
.git/config present: true

CC version: Apple clang version 14.0.0 (clang-1400.0.29.202)
thirdparty/tcc status: thirdparty-macos-amd64 46662e20-dirty

Note

You can use the 👍 reaction to increase the issue's priority for developers.

Please note that only the 👍 reaction to the issue itself counts as a vote.
Other reactions and those to comments will not be taken into account.

@xiusin xiusin added the Bug This tag is applied to issues which reports bugs. label Jan 8, 2024
@xiusin xiusin changed the title If use sort_with_compare, it will report an error If use sort_with_compare, it will report an error Jan 8, 2024
@JalonSolov
Copy link
Contributor

Does it fail when compiling? Or is this just a question about what's displayed in vscode/codeium/whatever editor that is?

@xiusin
Copy link
Contributor Author

xiusin commented Jan 9, 2024

@JalonSolov Compilation can also fail, reminding and editors should be consistent.

@shove70
Copy link
Contributor

shove70 commented Jan 10, 2024

Make sure you didn't make a typo:
AccountPostion
AccountPosition

pub fn (mut api App) api_account_position() vweb.Result {
    mut postions := []AccountPostion{} // some items   // <==  AccountPostion ???

    for i, mut postion in postions {
		postion.recid = postion.inst_id
		if postion.mgn_ratio.f64() * 100 <= 300 {
			postion.w2ui.style = 'background-color: #f3d6e3'
		} else if postion.upl_ratio.f64() * 100 < -50 {
			postion.w2ui.style = 'background-color: rgb(242, 250, 140)'
		} else {
			mut ratio := 0
			if postion.lever.f64() >= 20 {
				ratio = 50
			} else if postion.lever.f64() >= 10 {
				ratio = 30
			} else if postion.lever.f64() >= 3 {
				ratio = 20
			}
			if postion.upl_ratio.f64() * 100 > ratio {
				postion.w2ui.style = 'background-color: #C2F5B4'
			}
		}
		postions[i] = postion
	}

	request := api.query['request'] or { '{}' }
	dto := json.decode(RequestDto, request) or { RequestDto{} }
      // If you use sort_with_compare, it will report an error on the last line
	postions.sort_with_compare(fn [dto] (a &AccountPosition, b &AccountPosition) int {  // <==  AccountPosition ???
		if dto.sort.len == 0 {
			return 0
		}

		mut left := ''
		mut right := ''
		left, right = match dto.sort[0].field {
			'uplRatio' {
				a.upl_ratio, b.upl_ratio
			}
			'upl' {
				a.upl, b.upl
			}
			else {
				'', ''
			}
		}
		if left == right {
			return 0
		}

		if dto.sort[0].direction == 'desc' {
			return if left < right { -1 } else { 1 }
		} else {
			return if left > right { -1 } else { 1 }
		}
	})

	return api.json(postions) <- here 
}

@xiusin
Copy link
Contributor Author

xiusin commented Jan 10, 2024

@shove70 The code above is written manually by me, and there are some mistakes in it.

struct AccountPosition {
	adl               string @[omitempty]
        ...
}

v run main.v

main.v:236:9: error: undefined ident: `api`
  234 |     })
  235 | 
  236 |     return api.json(postions)
      |            ~~~
  237 | }
  238 |
main.v:236:13: error: cannot call a method using an invalid expression
  234 |     })
  235 | 
  236 |     return api.json(postions)
      |                ~~~~~~~~~~~~~~
  237 | }
  238 |
main.v:236:2: error: `api.json(postions)` used as value
  234 |     })
  235 | 
  236 |     return api.json(postions)
      |     ~~~~~~~~~~~~~~~~~~~~~~~~~
  237 | }
  238 |

@shove70
Copy link
Contributor

shove70 commented Jan 10, 2024

Whether this word is wrong or not, take a look at the 2 inconsistencies I've highlighted in your code.

image

With the correct change, 'postions.sort_with_compare' does not affect compilation!

@xiusin
Copy link
Contributor Author

xiusin commented Jan 10, 2024

@shove70 Oh, it might be my version issue. Let me try again. Thank you.

@xiusin
Copy link
Contributor Author

xiusin commented Jan 10, 2024

@shove70 If you use the following code, you will encounter compilation errors

postions.sort_with_compare(fn [dto] (a &AccountPosition, b &AccountPosition) int  // failed
postions.sort_with_compare(fn (a &AccountPosition, b &AccountPosition) int  // success

It will report the error of the next function

  243 | 
  244 | @['/api/account/balance'; get]
  245 | pub fn (mut api App) api_account_balance() vweb.Result {
      |             ~~~
  246 |     data := api.get_account_balance() or { return api.failed(err) }
  247 |     return api.json(data)

@xiusin
Copy link
Contributor Author

xiusin commented Jan 10, 2024

Currently, there seems to be a compilation issue when capturing external variables.

@shove70
Copy link
Contributor

shove70 commented Jan 11, 2024

Can you reproduce bugs by making your code as simple as possible? And provide the error information of V report as much as possible, thank you.

In general, when reporting a BUG, you should try to provide the simplest but complete code and pinpoint the core problem so that the developer can fix it quickly.

On the other hand, if the developer has to guess, progress can be very slow.

import vweb
import json

struct App {
	vweb.Context
}

struct AccountPosition {}
struct RequestDto {}
struct Balance {}

pub fn (mut api App) api_account_position() vweb.Result {
    mut postions := []AccountPosition{}

	request := api.query['request'] or { '{}' }
	dto := json.decode(RequestDto, request) or { RequestDto{} }
 
 	postions.sort_with_compare(fn [dto] (a &AccountPosition, b &AccountPosition) int {
		println(dto)
		return 0
	})

	return api.json(postions)
}

@['/api/account/balance'; get]
pub fn (mut api App) api_account_balance() vweb.Result {
    data := Balance {}
    return api.json(data)
}

This code does not report any issues with the closure parameter capture, compiles correctly, and does not affect the next function.

@xiusin
Copy link
Contributor Author

xiusin commented Jan 11, 2024

@shove70 The following code cannot be compiled

module main

import os
import net.http
import json
import vweb
import db.sqlite

struct Api {
	vweb.Context
	domain     string = 'https://demo.baidu.com'
	key        string @[vweb_global]
	secret     string @[vweb_global]
	passpharse string @[vweb_global]
pub mut:
	db sqlite.DB
}

@[table: 'okx_position_items']
struct OkxPositionItemModel {
	id        int    @[primary; sql: serial]
	inst_id   string @[sql_type: 'TEXT']
	inst_type string @[sql_type: 'TEXT']
	star      bool   @[sql_type: 'INTEGER']
}

pub fn Api.new(key string, secret string, passphrase string) !&Api {
	mut api := &Api{
		key: key
		secret: secret
		passpharse: passphrase
		db: sqlite.connect(':memory:')!
	}

	api.db.synchronization_mode(sqlite.SyncMode.off)!
	api.db.journal_mode(sqlite.JournalMode.memory)!

	sql api.db {
		create table OkxPositionItemModel
	}!

	return api
}

fn (mut api Api) get_account_balance() ![]AccountBalance {
	uri := '/api/v5/account/balance'
	return api.request[Response[[]AccountBalance]](uri, .get)!.data
}

fn (mut api Api) get_account_positions() ![]AccountPosition {
	uri := '/api/v5/account/positions'
	return api.request[Response[[]AccountPosition]](uri, .get)!.data
}

fn (mut api Api) request[T](path string, method http.Method, params ...map[string]string) !T {
	url_ := '${api.domain}${path}'

	mut request := http.new_request(method, url_, '')
	mut headers := http.new_header()

	if method == .post {
		headers.add(.content_type, 'application/json')
		headers.add(.accept, 'application/json')
	}

	if params.len > 0 {
		request.data = json.encode(params[0])
	}

	request.header = headers
	$if !windows {
		proxy := os.getenv_opt('https_proxy') or { os.getenv('HTTPS_PROXY') }
		if proxy.len > 0 {
			request.proxy = http.new_http_proxy(proxy)!
		}
	}

	resp := request.do()!

	if resp.status() != .ok && resp.status() != .no_content {
		err := json.decode(ErrMsg, resp.body) or {
			ErrMsg{
				msg: '${err}'
			}
		}
		return error(err.msg)
	}

	return json.decode(T, resp.body)!
}

@['/api/account/positions'; get]
pub fn (mut api Api) api_account_position() vweb.Result {
	mut postions := api.get_account_positions() or { return api.failed(err) }
	for i, mut postion in postions {
		postion.recid = postion.inst_id
		if postion.mgn_ratio.f64() * 100 <= 300 {
			postion.w2ui.style = 'background-color: #f3d6e3'
		} else if postion.upl_ratio.f64() * 100 < -50 {
			postion.w2ui.style = 'background-color: rgb(242, 250, 140)'
		} else {
			mut ratio := 0
			if postion.lever.f64() >= 20 {
				ratio = 50
			} else if postion.lever.f64() >= 10 {
				ratio = 30
			} else if postion.lever.f64() >= 3 {
				ratio = 20
			}
			if postion.upl_ratio.f64() * 100 > ratio {
				postion.w2ui.style = 'background-color: #C2F5B4'
			}
		}
		postions[i] = postion
	}

	request := api.query['request'] or { '{}' }
	dto := json.decode(RequestDto, request) or { RequestDto{} }

	postions.sort_with_compare(fn [dto] (a &AccountPosition, b &AccountPosition) int {
		if dto.sort.len == 0 {
			return 0
		}
		mut left := ''
		mut right := ''
		left, right = match dto.sort[0].field {
			'uplRatio' {
				a.upl_ratio, b.upl_ratio
			}
			'upl' {
				a.upl, b.upl
			}
			else {
				'', ''
			}
		}
		if left == right {
			return 0
		}

		if dto.sort[0].direction == 'desc' {
			return if left < right { -1 } else { 1 }
		} else {
			return if left > right { -1 } else { 1 }
		}
	})

	return api.json(postions)
}

@['/api/account/balance'; get]
pub fn (mut api Api) api_account_balance() vweb.Result {
	data := api.get_account_balance() or { return api.failed(err) }
	return api.json(data)
}

pub fn (mut api Api) failed(err IError) vweb.Result {
	return api.json(ErrMsg{ message: err.msg(), status: 'error' })
}

fn (mut api Api) serve() {
	vweb.run(&api, 8090)
}

fn main() {
	key := os.getenv('OKX_API_KEY')
	secret := os.getenv('OKX_API_SECRET')
	passphrase := os.getenv('OKX_PASSPHRASE')

	mut api := Api.new(key, secret, passphrase)!
	api.serve()
}

struct Response[T] {
	code string @[omitempty]
	msg  string @[omitempty]
	data T      @[omitempty]
}

struct AccountBalanceDetail {
	avail_bal       string @[json: 'availBal'; omitempty]
	avail_eq        string @[json: 'availEq'; omitempty]
	cash_bal        string @[json: 'cashBal'; omitempty]
	ccy             string @[omitempty]
	cross_liab      string @[json: 'crossLiab'; omitempty]
	dis_eq          string @[json: 'disEq'; omitempty]
	eq              string @[omitempty]
	eq_usd          string @[json: 'eqUsd'; omitempty]
	fixed_bal       string @[json: 'fixedBal'; omitempty]
	frozen_bal      string @[json: 'frozenBal'; omitempty]
	interest        string @[omitempty]
	iso_eq          string @[json: 'isoEq'; omitempty]
	iso_liab        string @[json: 'isoLiab'; omitempty]
	iso_upl         string @[json: 'isoUpl'; omitempty]
	liab            string @[omitempty]
	max_loan        string @[json: 'maxLoan'; omitempty]
	mgn_ratio       string @[json: 'mgnRatio'; omitempty]
	notional_lever  string @[json: 'notionalLever'; omitempty]
	ord_frozen      string @[json: 'ordFrozen'; omitempty]
	twap            string @[omitempty]
	u_time          string @[json: 'uTime'; omitempty]
	upl             string @[omitempty]
	upl_liab        string @[json: 'uplLiab'; omitempty]
	stgy_eq         string @[json: 'stgyEq'; omitempty]
	spot_in_use_amt string @[json: 'spotInUseAmt'; omitempty]
	borrow_froz     string @[json: 'borrowFroz'; omitempty]
	spot_iso_bal    string @[json: 'spotIsoBal'; omitempty]
}

struct AccountBalance {
	adj_eq       string                 @[json: 'adjEq'; omitempty]
	borrow_froz  string                 @[json: 'borrowFroz'; omitempty]
	details      []AccountBalanceDetail @[omitempty]
	imr          string                 @[omitempty]
	iso_eq       string                 @[json: 'isoEq'; omitempty]
	mgn_ratio    string                 @[json: 'mgnRatio'; omitempty]
	mmr          string                 @[omitempty]
	notional_usd string                 @[json: 'notionalUsd'; omitempty]
	ord_froz     string                 @[json: 'ordFroz'; omitempty]
	total_eq     string                 @[json: 'totalEq'; omitempty]
	u_time       string                 @[json: 'uTime'; omitempty]
}

struct ErrMsg {
	msg     string @[omitempty]
	message string @[omitempty]
	status  string @[omitempty]
}

struct W2ui {
pub mut:
	style   string
	class   string
	summary bool
	event   string
}

struct AccountPosition {
	adl               string @[omitempty]
	avail_pos         string @[json: 'availPos'; omitempty]
	avg_px            string @[json: 'avgPx'; omitempty]
	c_time            string @[json: 'cTime'; omitempty]
	ccy               string @[omitempty]
	delta_b_s         string @[json: 'deltaBS'; omitempty]
	delta_p_a         string @[json: 'deltaPA'; omitempty]
	gamma_b_s         string @[json: 'gammaBS'; omitempty]
	gamma_p_a         string @[json: 'gammaPA'; omitempty]
	imr               string @[omitempty]
	inst_id           string @[json: 'instId'; omitempty]
	inst_type         string @[json: 'instType'; omitempty]
	interest          string @[omitempty]
	idx_px            string @[json: 'idxPx'; omitempty]
	last              string @[omitempty]
	usd_px            string @[json: 'usdPx'; omitempty]
	be_px             string @[json: 'bePx'; omitempty]
	lever             string @[omitempty]
	liab              string @[omitempty]
	liab_ccy          string @[json: 'liabCcy'; omitempty]
	liq_px            string @[json: 'liqPx'; omitempty]
	mark_px           string @[json: 'markPx'; omitempty]
	margin            string @[omitempty]
	mgn_mode          string @[json: 'mgnMode'; omitempty]
	mgn_ratio         string @[json: 'mgnRatio'; omitempty]
	mmr               string @[omitempty]
	notional_usd      string @[json: 'notionalUsd'; omitempty]
	opt_val           string @[json: 'optVal'; omitempty]
	p_time            string @[json: 'pTime'; omitempty]
	pos               string @[omitempty]
	pos_ccy           string @[json: 'posCcy'; omitempty]
	pos_id            string @[json: 'posId'; omitempty]
	pos_side          string @[json: 'posSide'; omitempty]
	spot_in_use_amt   string @[json: 'spotInUseAmt'; omitempty]
	spot_in_use_ccy   string @[json: 'spotInUseCcy'; omitempty]
	theta_b_s         string @[json: 'thetaBS'; omitempty]
	theta_p_a         string @[json: 'thetaPA'; omitempty]
	trade_id          string @[json: 'tradeId'; omitempty]
	biz_ref_id        string @[json: 'bizRefId'; omitempty]
	biz_ref_type      string @[json: 'bizRefType'; omitempty]
	quote_bal         string @[json: 'quoteBal'; omitempty]
	base_bal          string @[json: 'baseBal'; omitempty]
	base_borrowed     string @[json: 'baseBorrowed'; omitempty]
	base_interest     string @[json: 'baseInterest'; omitempty]
	quote_borrowed    string @[json: 'quoteBorrowed'; omitempty]
	quote_interest    string @[json: 'quoteInterest'; omitempty]
	u_time            string @[json: 'uTime'; omitempty]
	upl               string @[omitempty]
	upl_last_px       string @[json: 'uplLastPx'; omitempty]
	upl_ratio         string @[json: 'uplRatio'; omitempty]
	upl_ratio_last_px string @[json: 'uplRatioLastPx'; omitempty]
	vega_b_s          string @[json: 'vegaBS'; omitempty]
	vega_p_a          string @[json: 'vegaPA'; omitempty]
	realized_pnl      string @[json: 'realizedPnl'; omitempty]
	pnl               string @[omitempty]
	fee               string @[omitempty]
	funding_fee       string @[json: 'fundingFee'; omitempty]
	liq_penalty       string @[json: 'liqPenalty'; omitempty]
pub mut:
	w2ui  W2ui   @[json: 'w2ui'; omitempty]
	recid string @[omitempty]
}

struct RequestDto {
pub mut:
	limit  i64
	offset i64
	sort   []struct {
		field     string
		direction string
	}
}

PS C:\Users\Administrator\Desktop\xiusin-zig-examples> v run .\main_bad.v
main_bad.v:148:9: error: undefined ident: `api`
  146 |     })
  147 |
  148 |     return api.json(postions)
      |            ~~~
  149 | }
  150 |
main_bad.v:148:13: error: cannot call a method using an invalid expression
  146 |     })
  147 |
  148 |     return api.json(postions)
      |                ~~~~~~~~~~~~~~
  149 | }
  150 |
main_bad.v:148:2: error: `api.json(postions)` used as value
  146 |     })
  147 |
  148 |     return api.json(postions)
      |     ~~~~~~~~~~~~~~~~~~~~~~~~~
  149 | }
  150 |

@shove70
Copy link
Contributor

shove70 commented Jan 11, 2024

struct RequestDto {
pub mut:
	limit  i64
	offset i64
	sort   []struct {   // <-----   the field name: sort
		field     string
		direction string
	}
}

The struct's field name 'sort' causes problems, so you can temporarily change the name to compile.

Whether sort can be used as a field name needs to be discussed, but I think it should be allowed and fixed.

Thank you for your feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug This tag is applied to issues which reports bugs.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants